Compare commits

..

139 Commits

Author SHA1 Message Date
Roy 789d9b3a81 [update] fix hstia gain 2022-11-15 11:51:16 +08:00
Roy 0d0427ed14 [update] receive hsrtia & lprtia gain level 2022-11-09 17:19:48 +08:00
Roy d434509c5b [update] new hsrtia function 2022-11-09 16:03:45 +08:00
Roy 787d76d48c [update] update eis instruction 2022-11-08 17:55:20 +08:00
Roy 50f2432088 [update] update number of mode 2022-11-08 17:28:03 +08:00
Roy 1cff19ac58 [update] update GENERAL_HS_RTIA parameter 2022-11-08 16:13:20 +08:00
Roy baef447c0e [update] update EIS_AVERAGE_NUM parameter 2022-11-08 15:57:52 +08:00
Roy ee9c13d4c5 [update] update EIS_DELAY parameter 2022-11-08 15:44:57 +08:00
Roy 9076f2f10b [update] update EIS_SCALE parameter 2022-11-08 15:36:22 +08:00
Roy 9b2e2964b0 [update] update EIS_PPD parameter 2022-11-08 14:49:07 +08:00
Roy 2622109c89 [update] update EIS_FREQ parameter 2022-11-08 14:35:32 +08:00
Roy a3fe6b87af [update] update EIS_AC_AMP parameter 2022-11-08 14:24:07 +08:00
Roy 64419ca1c5 [update] update EIS_DC_BIAS parameter 2022-11-08 14:17:31 +08:00
Roy 7d77c44741 [update] update EIS_FREQ parameter 2022-11-08 12:09:42 +08:00
Roy 29b4dd5cc7 [update] update EIS_FREQ parameter 2022-11-08 12:07:49 +08:00
Roy f151ae6fce [update] delete FREQ_START & FREQ_STOP parameter 2022-11-08 11:08:01 +08:00
peterlu14 e535e3d2b1 Merge remote-tracking branch 'origin/EIS_10test' into release/v1.7.0/fix_EIS_freq-RT 2022-11-08 09:38:19 +08:00
10 06c36aa737 Merge remote-tracking branch 'origin/dev/RT_mode' into EIS_10test 2022-11-07 16:54:28 +08:00
10 402022c451 cutoff freq 2022-11-07 16:44:54 +08:00
Roy 4daff72d39 [update] update RT mode 2022-10-27 17:43:16 +08:00
Roy f99719832a [update] short instruction for RT mode 2022-10-27 17:13:38 +08:00
Roy 58e09bfcda [update] hide mem board message 2022-10-26 10:23:50 +08:00
Roy 55780514b9 [update] new RT mode 2022-10-26 10:23:12 +08:00
peterlu14 936514871f [update] timeout 3 -> 5 2022-10-18 11:23:53 +08:00
peterlu14 f25d9221c6 Merge branch 'release/v1.6.9/fix_phase_90ToN90' into release/v1.6.7/scheduler_debug 2022-10-14 10:53:40 +08:00
peterlu14 2ee9fa6b19 [update] project device change 2022-10-14 10:52:41 +08:00
10 fcc39dbfed Merge branch 'release/v1.6.9/fix_phase_90ToN90' into EIS_10test 2022-10-13 15:28:39 +08:00
10 e2f7bba961 fix phase in PEIS mode 2022-10-13 15:27:27 +08:00
10 1174d54bc0 fix phase in PEIS mode 2022-10-13 15:13:00 +08:00
peterlu14 bff75dc49e Merge commit '35912f614e7283bb4b8df5355952162fea9a9395' into release/v1.6.9/fix_phase_90ToN90 2022-10-12 17:18:49 +08:00
peterlu14 35912f614e [update] EIS Mini vt mode add 2022-10-12 17:18:14 +08:00
10 cfc4e39c8a force raw phase and raw phase - ideal phase stay in [90, -90) in PEIS mode 2022-10-12 16:41:55 +08:00
10 8c4916d1e8 fix phase calibration 2022-10-11 17:19:40 +08:00
Roy e3c252f204 [update] FREQ 133333 2022-10-05 11:58:37 +08:00
Roy c2164da48b [update] new vt mode on EIS 2022-10-05 11:16:09 +08:00
Roy ab2d746afb Merge branch 'release/v1.6.7/scheduler_cycle' into release/v1.6.7/scheduler_debug 2022-10-05 10:57:53 +08:00
Roy 8a870a860a [update] socket listen 3 -> 20 2022-10-05 10:57:30 +08:00
Roy f4c5cf0135 [update] socket timeout 1s -> 3s 2022-10-04 13:53:53 +08:00
Roy 1f01fd3b9b [update] count +1 when start 2022-10-04 13:53:30 +08:00
Roy d1fe388c27 [debug] fix multi device in one project stop problem 2022-10-04 13:42:03 +08:00
Roy 91d5e73c5e [debug] fix after task run equal error 2022-10-04 13:41:37 +08:00
Roy d1b6c2892f [debug] configurations key error 2022-10-04 13:18:38 +08:00
Roy 4243a13536 Merge remote-tracking branch 'origin/dev/fix_no_data' into release/v1.6.7/scheduler_debug 2022-09-30 10:58:41 +08:00
Roy 97188abff8 [update] uart write timeout 0.01 -> 1 2022-09-30 10:56:47 +08:00
Roy 9d8178d11a [update] add project cycle 2022-09-30 10:56:37 +08:00
Roy bbde653a8e [update] update cali value 2022-09-28 14:50:22 +08:00
Roy 6c0cef7925 [update] test function: print mem board info 2022-09-27 14:38:00 +08:00
Roy 3bbf0c912a [update] test function: print mem board info 2022-09-27 13:41:32 +08:00
Roy 4333958ebe [update] fix eis's FREQ default value 2022-09-16 17:49:28 +08:00
Roy 3239a691e3 [update] test function: print ram info 2022-09-16 13:12:40 +08:00
Roy 30183788d8 [update] test function: print ram info 2022-09-14 18:12:53 +08:00
Roy 13df921b1c [update] test function: print ram info 2022-09-14 17:14:47 +08:00
Roy d182a04ed3 [update] add channel data 2022-09-14 15:36:01 +08:00
Roy 35a09ff9a0 [update] switch mode set default highz & time_duration in Elite_EDC 2022-09-06 18:51:32 +08:00
Roy e134b9780c [update] add new api set_project & add new condition until_button_trigger & add new action idle 2022-09-06 16:28:38 +08:00
peterlu14 df39f241b3 [update] add battery 2022-08-22 19:57:02 +08:00
peterlu14 0b72ac0c9d Merge branch 'dev/scheduler_cycle' into release/v1.6.6/merge_scheduler 2022-08-22 17:42:57 +08:00
JayC319 0afbe66229 [update] edc 1.5 library 2022-08-22 13:58:39 +08:00
108000207 9846cfd708 [update] set _time_interval as 0.1 to avoid delay 2022-08-19 15:44:51 +08:00
108000207 b4ad2a7fba [update] remove useless comments 2022-08-18 17:51:51 +08:00
108000207 675fdc2226 [update] cycle_next use uuid version 2022-08-18 17:39:59 +08:00
108000207 a847b1222d [debug] fix the bug of first task can't idle 2022-08-17 15:51:29 +08:00
108000207 bd0c36923a [update] scheduler cycle version 1 2022-08-17 11:50:22 +08:00
peterlu14 612785f51a [update] EIS show data 2022-08-16 19:40:27 +08:00
peterlu14 7dbf09e9a5 [update] EIS show data 2022-08-16 19:39:06 +08:00
peterlu14 ee64d43de1 [update] ca instruction b0 -> D3 2022-08-16 19:31:33 +08:00
peterlu14 60b91f0c1e [update] EIS add show data 2022-08-16 19:15:04 +08:00
Roy 8ac01bdf54 [update] update eis library 2022-08-16 19:10:18 +08:00
JayC319 0f90b16b6e [update] library product number 2022-08-16 17:35:06 +08:00
peterlu14 cd98a14e84 [debug] fix idle send instruction & remove deepcopy & close task by device 2022-08-16 14:25:37 +08:00
peterlu14 2e97ad23eb [debug] fix parameter empty 2022-08-16 12:11:35 +08:00
108000207 e0dd5a6972 [update] add schdeuler cycle attribute 2022-08-16 11:34:47 +08:00
Roy 76e0a150d1 Merge remote-tracking branch 'origin/dev/Cali_mode' into dev/cc_cp_separate 2022-08-15 18:11:20 +08:00
JayC319 ecd4b9325d [update] 2022-08-15 18:09:40 +08:00
peterlu14 978b1254f0 Merge branch 'dev/debug' into dev/cc_cp_separate 2022-08-11 13:53:13 +08:00
peterlu14 26e02f2d40 [update] add data_show function print device data 2022-08-11 00:58:30 +08:00
peterlu14 ead98fe8da [debug] fix running_task is None bug 2022-08-10 14:03:04 +08:00
Roy 257958768f [update] new ca mode instruvtion 2022-08-05 18:34:33 +08:00
peterlu14 dc4e1bd233 Merge branch 'dev/fix_final_data_loss' into dev/cc_cp_separate 2022-08-05 10:27:33 +08:00
peterlu14 42025d2243 [update] fix cp mode voltage problem 2022-08-05 10:26:13 +08:00
Roy b341dbf073 [update] update instruction of cp mode 2022-08-04 18:12:23 +08:00
Roy 20f6f126b0 [update] fix STEP_TIME para 2022-08-04 16:48:51 +08:00
Roy bf4a00db1a [update] remove CC_ZERO instruction 2022-07-29 11:24:29 +08:00
peterlu14 0b7a650b95 [debug] fix final data loss & flag stop after writer write 2022-07-29 11:11:46 +08:00
Roy 062613c681 [update] fix step time on IV & Cycle-IV mode 2022-07-28 16:36:34 +08:00
Roy bffaff310b [update] update file name of elite library 2022-07-26 13:14:37 +08:00
Roy 06bf262d59 [update] new device library for elite eis1.1 mini 2022-07-13 10:03:40 +08:00
Roy b2f9d98336 [update] update elite device library 2022-07-06 16:23:12 +08:00
Roy a6b523404b [update] update elite device library 2022-07-05 18:20:32 +08:00
peterlu14 6c232b3b07 [update] fix struct.pack type error support signed int & max number type 2022-06-22 15:23:44 +08:00
peterlu14 cfc2bf1d83 Merge remote-tracking branch 'origin/rel/v.1.6.4/read_ram_debug' into rel/v.1.6.5/restruct_data_format 2022-06-22 13:18:03 +08:00
Roy 2b60e68197 [update] update eis decoder code 2022-06-22 13:11:57 +08:00
peterlu14 efb5e9aeb6 [update] add list struct update in new way & fix list parameter not valid & collection nested error & fixed encoder struct bytes wrong (singed, unsigned) 2022-06-17 19:54:42 +08:00
peterlu14 b4d88a0e67 [update] change elite pulse sensing paramter in array 2022-06-17 19:51:05 +08:00
peterlu14 6029ff6fe1 [update] FREQ & DPV_curr_rec max_min to array and add update array format 2022-06-15 16:48:23 +08:00
Roy 6efc5e1097 [update] hide log message 2022-06-10 17:36:13 +08:00
Roy a23394d3d1 Merge branch 'dev/eis_parameter_bug' into rel/v.1.6.4/read_ram_debug 2022-06-10 17:31:45 +08:00
Roy c96f76f438 [update] read RAM data bug 2022-06-10 17:22:10 +08:00
Roy f0f1c9fc49 [update] update eis json 2022-06-10 17:20:58 +08:00
peterlu14 512c80af40 [update] add new info id,name,status,mac_address,memory_board 2022-06-06 18:52:12 +08:00
Roy 499964b287 [update] fix TIME_DURATION in eis devlib 2022-05-23 17:42:12 +08:00
Roy 16f12d40bf [update] improve cp and cc mode - speed and resistance value 2022-05-20 12:11:56 +08:00
peterlu14 63c1ba8efb [update] update decorder mode in I4V4Z4T4 2022-05-18 16:16:17 +08:00
Roy 4a28348db4 [update] fix cp mode instruction and decoder 2022-05-18 11:06:23 +08:00
peterlu14 64dfe87d05 [update] remove decorder rebuild problem & add new parameter to control time duration 2022-05-18 10:19:08 +08:00
peterlu14 f7a5a867a4 [update] fix memory counter 2022-05-06 13:50:09 +08:00
peterlu14 1accaa9b9f [update] delete logger 2022-05-06 11:25:30 +08:00
peterlu14 b810e35fb2 Merge branch 'feature/get-running-project-flow' into rel/v1.6.1/cp_mode 2022-05-06 10:39:51 +08:00
peterlu14 82c9d2b0e3 [update] add clean logger script 2022-05-06 10:39:47 +08:00
peterlu14 e5a3f33b9f [update] add cp mode 2022-05-06 10:36:17 +08:00
peterlu14 1dd4ae2ce4 [update] add stop project api & fix uuid problem & get all projects & as_json problem 2022-05-04 18:07:05 +08:00
peterlu14 515cc9f7a2 [update] fix stop close writer losing data problem 2022-04-29 17:18:48 +08:00
peterlu14 9b92249fdb Merge branch 'feature/project' into rel/v1.6.0/highz 2022-04-27 14:01:07 +08:00
peterlu14 adcc13b4de [update] idle device not sending instruction 2022-04-27 13:26:05 +08:00
peterlu14 0cd0fd7027 [update] project task name rename 2022-04-27 13:24:31 +08:00
Roy 5228290eac [update] fix 1.5re.json about highz 2022-04-27 13:16:29 +08:00
LuoYiTing 034b7976cd Update README.md 2022-04-25 03:55:34 +00:00
peterlu14 fa8c219f76 Merge branch 'rel/v1.5.1' into feature/project 2022-04-25 10:48:22 +08:00
peterlu14 f233c019fd [update] auto get eth0 mac address 2022-04-25 10:36:02 +08:00
peterlu14 ced466f3aa [update] add condition & first task issue & add boardcast 2022-04-18 01:52:52 +08:00
peterlu14 f36906c034 [update] restruct project 2022-04-17 23:05:21 +08:00
peterlu14 0b5c62e525 [update] temp save 2022-04-16 10:50:37 +08:00
peterlu14 abe86238ca remove print messages 2022-04-13 15:58:27 +08:00
peterlu14 f9ab0bc59b [update] remove duplicate code 2022-04-13 15:49:04 +08:00
peterlu14 5dbe231c73 [update] add cacheClient communicate with control server & add comment 2022-04-13 14:08:57 +08:00
peterlu14 c721950bf7 [update] add complete device status 2022-04-12 14:28:04 +08:00
peterlu14 70c0271771 [remove] duplicate code 2022-04-11 16:35:04 +08:00
peterlu14 13825fe9ff [update] hide print 2022-04-08 18:22:44 +08:00
peterlu14 dd2e31d01f [update] fix index problem 2022-04-08 18:16:31 +08:00
peterlu14 455fa1f86b [update] fix stop error & relative_time 2022-04-08 11:17:07 +08:00
Roy 71850b31a8 [update] fix recording error 2022-04-07 12:33:02 +08:00
peterlu14 8d52fef4c1 [update] hide print message 2022-04-07 12:29:18 +08:00
peterlu14 e091f220fa Merge branch 'test/update_data_server' into rel/v1.4.0_schedule/channel_lost_data 2022-03-28 18:19:29 +08:00
Roy 2fd05d18ed [update] fix battery value 2022-03-25 13:41:48 +08:00
Roy 03011ebd5f Merge branch 'dev/check_sum/battery' into rel/v1.4.0_schedule/channel_lost_data 2022-03-25 12:11:05 +08:00
Roy 4b9bc30e28 [update] get battery value 2022-03-25 11:46:40 +08:00
Roy 4966113393 [update] use check sum 2022-03-25 11:44:52 +08:00
Roy 3371c21bbd [update] update log message 2022-03-25 11:34:30 +08:00
Roy afc87829d9 [update] head != tailer, delete data 2022-03-24 17:12:06 +08:00
45 changed files with 8439 additions and 2933 deletions
+2
View File
@@ -1,5 +1,7 @@
.DS_Store .DS_Store
*.cpython-37.opt-2.pyc *.cpython-37.opt-2.pyc
*.cpython-39-arm-linux-gnueabihf.so
*.
*.pyc *.pyc
*/__pycache__ */__pycache__
/.vscode /.vscode
+174 -38
View File
@@ -4,7 +4,7 @@ New goal on pi4 without kotlin and django, and with only one dataserver.
# Installation # Installation
### Get Raspbrain into SD card ### Get Raspbrain into SD card
###### Download Raspbian Buster Lite ###### Download Raspbian Bullseye Lite
>https://www.raspberrypi.org/downloads/raspberry-pi-os/ >https://www.raspberrypi.org/downloads/raspberry-pi-os/
@@ -14,7 +14,7 @@ New goal on pi4 without kotlin and django, and with only one dataserver.
lsblk lsblk
# copy data to sd card # copy data to sd card
sudo dd bs=4M if=yyyy-mm-dd-raspbian-buster.img of=/dev/sdX conv=fsync status=progress sudo dd bs=4M if=yyyy-mm-dd-raspios-bullseye-armhf-lite.img of=/dev/sdX conv=fsync status=progress
# enable ssh on first boot # enable ssh on first boot
add ssh.txt in boot folder add ssh.txt in boot folder
@@ -77,18 +77,22 @@ add ssh.txt in boot folder
###### Install dependencies ###### Install dependencies
sudo apt-get install vim git wiringpi build-essential libi2c-dev i2c-tools python-dev libffi-dev python3-pip postgresql sudo apt-get install vim git wiringpi build-essential libi2c-dev i2c-tools python-dev libffi-dev python3-pip postgresql npm
###### wiringpi conflict
need to install wiringpi: https://github.com/WiringPi/WiringPi
install instructions: https://github.com/WiringPi/WiringPi/blob/master/INSTALL
### Setup project ### Setup project
###### Clone project ###### Clone data server project
``` ```
cd ~ cd ~
git clone https://gitlab.com/bioproscientific/bioprorelife.git git clone https://gitlab.com/wisetop/controller/wisetopdataserver.git
``` ```
###### Install python dependencies ###### Install python dependencies
``` ```
cd ~/bioprorelife cd ~/wisetopdataserver
pip3 install -r requirements.txt pip3 install -r requirements.txt
``` ```
##### Packages version ##### Packages version
@@ -112,14 +116,14 @@ psycopg2 2.8.5
###### Build C extension ###### Build C extension
``` ```
cd ~/bioprorelife/python/biopro/ext/ cd ~/wisetopdataserver/python/biopro/ext/
rm -rf *.so build rm -rf *.so build
python3 setup.py build_ext --inplace python3 setup.py build_ext --inplace
``` ```
###### Check setup-uart file ###### Check setup-uart file
``` ```
cd ~/bioprorelife cd ~/wisetopdataserver/
sudo vim ./run-setup-uart.sh sudo vim ./run-setup-uart.sh
``` ```
##### Modify the code as following ##### Modify the code as following
@@ -149,44 +153,72 @@ sudo raspi-config
reboot reboot
``` ```
###### Set pi password
```
$cd ~
$passwd
Current password:raspberry
New password:5k6zj454778225
Retype new password:5k6zj454778225
```
###### Auto run program when device start ###### Auto run program when device start
``` ```
sudo vim /etc/rc.local sudo vim /etc/rc.local
``` ```
add the code following as: ###### add the code following as:
``` ```
sudo -H -u pi nohup /home/pi/bioprorelife/run-data-server.sh > /home/pi/.data_server.out & sudo -H -u pi nohup /home/pi/wisetopdataserver/run-data-server.sh > /home/pi/.data_server.out &
#sudo -H -u pi nohup /home/pi/wisetopdataserver/run-data-server.sh > /home/pi/.wisetop_data_$now.out &
``` ```
##### /etc/rc.local
```
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
now=$(date +'%F_%T')
sudo nohup systemctl restart apache2
sudo nohup systemctl restart mosquitto
nohup node /home/pi/wisetopapiserver/dist/app.js > /home/pi/.api_server.out &
sleep 5
sudo -H -u pi nohup /home/pi/wisetopdataserver/run-data-server.sh > /home/pi/.data_server.out &
#sudo -H -u pi nohup /home/pi/wisetopdataserver/run-data-server.sh > /home/pi/.wisetop_data_$now.out &
exit 0
```
### MQTT broker install ### MQTT broker install
1. Install mosquitto ###### 1.Install mosquitto
``` $sudo apt-get install mosquitto mosquitto-clients
sudo apt-get install mosquitto mosquitto-clients
```
###### 2.Enable Remote Access
$sudo vim /etc/mosquitto/conf.d/default.conf
2. Enable Remote Access
```
sudo vim /etc/mosquitto/conf.d/default.conf
```
add the code following as: add the code following as:
``` ```
listener 1883 listener 1883
protocol mqtt protocol mqtt
listener 8083 listener 8083
protocol websockets protocol websockets
allow_anonymous true
``` ```
restart mqtt broker ###### 3.restart mqtt broker
``` $sudo systemctl restart mosquitto
sudo systemctl restart mosquitto
```
3. Robust MQTT ###### 4.Robust MQTT
create mosquitto_restart.sh create mosquitto_restart.sh
```
cd ~ $cd ~
sudo vim mosquitto_restart.sh $sudo vim mosquitto_restart.sh
```
add the code following as: add the code following as:
``` ```
if [ "`ps -aux | grep /usr/sbin/mosquitto | wc -l`" == "1" ] if [ "`ps -aux | grep /usr/sbin/mosquitto | wc -l`" == "1" ]
@@ -200,25 +232,129 @@ fi
echo "$SERVICE is currently running" >> /home/ubuntu/cron.log echo "$SERVICE is currently running" >> /home/ubuntu/cron.log
exit 0 exit 0
``` ```
add mosquitto_restart.sh to root routing ###### 5.add mosquitto_restart.sh to root routing
``` $sudo chmod +x mosquitto_restart.sh
sudo chmod +x mosquitto_restart.sh $sudo -i
sudo -i $crontab -e
crontab -e
```
add the code following as: add the code following as:
``` ```
*/5 * * * * /home/pi/mosquitto_restart.sh */5 * * * * /home/pi/mosquitto_restart.sh
``` ```
3. Auto run MQTT broker when when pi-start ###### 6.Auto run MQTT broker when when pi-start
``` $sudo vim /etc/rc.local
sudo vim /etc/rc.local
```
add the code following as: add the code following as:
``` ```
sudo nohup systemctl restart mosquitto sudo nohup systemctl restart mosquitto
``` ```
### Setup routed wireless access point ### Setting up a Routed Wireless Access Point
###### 1.Install AP and Management Software
$sudo apt install hostapd
$sudo systemctl unmask hostapd
$sudo systemctl enable hostapd
$sudo apt install dnsmasq
$sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent
###### 2.Set up the Network Router
$sudo nano /etc/dhcpcd.conf
```
interface wlan0
static ip_address=192.168.2.1/24
nohook wpa_supplicant
```
$sudo nano /etc/sysctl.d/routed-ap.conf
```
# Enable IPv4 routing
net.ipv4.ip_forward=1
```
$sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$sudo netfilter-persistent save
$sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
$sudo nano /etc/dnsmasq.conf
```
interface=wlan0 # Listening interface
dhcp-range=192.168.2.2,192.168.2.255,255.255.255.0,24h
# Pool of IP addresses served via DHCP
domain=wlan # Local wireless DNS domain
address=/gw.wlan/192.168.2.1
# Alias for this router
```
###### 3.Ensure Wireless Operation
$sudo rfkill unblock wlan
###### 4.Configure the AP Software
$sudo nano /etc/hostapd/hostapd.conf
```
country_code=TW
interface=wlan0
ssid=WTP_NONE
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=00000000
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
# 802.11n support
ieee80211n=1
# make raspberry pi dongle fast
wme_enabled=1
# ht_capab: HT capabilities, enable 40MHz
ht_capab=[HT40+][SHORT-GI-40]
```
###### 5.Running the new Wireless AP
$sudo systemctl reboot
### Set web site
$sudo vim ./sites-available/000-default.conf
```
<VirtualHost *:8080> #80------>8080
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
<VirtualHost *:80>
ServerAdmin bioprovue@localhost
DocumentRoot /var/www/bioprovuebuild
</VirtualHost>
```
##### raspberry website document: ##### raspberry website document:
> https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md > https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
+15 -3
View File
@@ -1578,10 +1578,22 @@ class ControlAPI(metaclass=Router):
raise NotImplementedError() raise NotImplementedError()
def run_project(self, project) -> bool: def run_project(self, project) -> bool:
print('create_project', project) raise NotImplementedError()
self._project_manager.create(project)
return False
def get_running_project(self) -> bool:
raise NotImplementedError()
def stop_project(self, project) -> bool:
raise NotImplementedError()
def set_project(self, project, content) -> bool:
raise NotImplementedError()
def set_project_cycle(self, project, index, content) -> bool:
raise NotImplementedError()
def show_device_data(self, device) -> bool:
raise NotImplementedError()
# noinspection PyAbstractClass # noinspection PyAbstractClass
class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)): class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)):
+11
View File
@@ -130,6 +130,14 @@ class DataAPI(metaclass=abc.ABCMeta):
def hardware_test(self) -> JSON_OBJECT: def hardware_test(self) -> JSON_OBJECT:
"""""" """"""
pass pass
@abc.abstractmethod
def show_data(self, device: Union[int, Device]):
"""show device data
:param device: device ID
"""
pass
# noinspection PyAbstractClass # noinspection PyAbstractClass
@@ -191,6 +199,9 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
def stop_sync(self, *device: Union[int, Device]): def stop_sync(self, *device: Union[int, Device]):
self.send_command('stop_sync', *self._to_device_id(*device)) self.send_command('stop_sync', *self._to_device_id(*device))
def show_data(self, device: int):
self.send_command('show_data', device)
@staticmethod @staticmethod
def _to_device_id(*device: Union[int, Device]) -> Tuple[int, ...]: def _to_device_id(*device: Union[int, Device]) -> Tuple[int, ...]:
+3 -2
View File
@@ -536,7 +536,7 @@ class CC2650Device(Device):
self._master.log_warn('device', self.device_id, 'update_battery_info no response') self._master.log_warn('device', self.device_id, 'update_battery_info no response')
else: else:
if data is not None and len(data) == 4 : if data is not None and len(data) > 2 :
battery = struct.unpack('<H', data[1:3])[0] battery = struct.unpack('<H', data[1:3])[0]
if battery is not None: if battery is not None:
self._battery = battery self._battery = battery
@@ -662,7 +662,7 @@ class CC2650Device(Device):
elif device_type == 'EISZeroOne': elif device_type == 'EISZeroOne':
i = 0 i = 0
request_times = 0 request_times = 0
while i < 7: while i < 13:
try: try:
# send # send
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i) code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
@@ -2035,6 +2035,7 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
# print("local_name = ", local_name) # print("local_name = ", local_name)
# addr type is don't care in BMD380 # addr type is don't care in BMD380
print('scan_response:', list(scan_response))
local_addr_type = int(scan_response[index:index + 1][0]) local_addr_type = int(scan_response[index:index + 1][0])
# local_addr_type = 0xFF # local_addr_type = 0xFF
index = index + 1 index = index + 1
+8 -8
View File
@@ -253,6 +253,7 @@ class DeviceInternalCommandHandler:
return True return True
# why inherit MasterDevice ?
class DeviceManager(MasterDevice, Synchronized): class DeviceManager(MasterDevice, Synchronized):
"""device manager. It manager the device libraries, found device, connected device """device manager. It manager the device libraries, found device, connected device
and the control of the master device. and the control of the master device.
@@ -267,7 +268,6 @@ class DeviceManager(MasterDevice, Synchronized):
options: DeviceManagerOptions, options: DeviceManagerOptions,
handler: Optional[DeviceInternalCommandHandler] = None): handler: Optional[DeviceInternalCommandHandler] = None):
""" """
:param options: manager options. :param options: manager options.
:param handler: device internal command handler :param handler: device internal command handler
""" """
@@ -277,6 +277,7 @@ class DeviceManager(MasterDevice, Synchronized):
if handler is None: if handler is None:
handler = DeviceInternalCommandHandler() handler = DeviceInternalCommandHandler()
# control server api
self._handler: DeviceInternalCommandHandler = handler self._handler: DeviceInternalCommandHandler = handler
self._options: DeviceManagerOptions = options self._options: DeviceManagerOptions = options
@@ -286,7 +287,9 @@ class DeviceManager(MasterDevice, Synchronized):
# hardware # hardware
self._interface = options.interface self._interface = options.interface
self._master: Optional[MasterDevice] = None self._master: Optional[MasterDevice] = None
# memory board
self._centralMaster: Optional[MasterDevice] = None self._centralMaster: Optional[MasterDevice] = None
# connected device
self._device: List[CompletedDevice] = [] self._device: List[CompletedDevice] = []
# demo device # demo device
@@ -336,6 +339,10 @@ class DeviceManager(MasterDevice, Synchronized):
def library_path(self) -> List[Path]: def library_path(self) -> List[Path]:
return self._repository.library_path return self._repository.library_path
def get_device_status(self, mac_address) -> Optional[DeviceLibrary]:
device = self.get_device(mac_address)
return device.status
@logging_info @logging_info
def reload_library(self): def reload_library(self):
"""reload device library""" """reload device library"""
@@ -562,7 +569,6 @@ class DeviceManager(MasterDevice, Synchronized):
@logging_verbose @logging_verbose
def get_device(self, device: Union[int, DeviceInfo]) -> Optional[CompletedDevice]: def get_device(self, device: Union[int, DeviceInfo]) -> Optional[CompletedDevice]:
print('get_device', device)
"""get connected device """get connected device
:param device: device ID or response info :param device: device ID or response info
@@ -1024,15 +1030,9 @@ class DeviceManager(MasterDevice, Synchronized):
raise RuntimeError(DEVICE_NOT_FOUND, device) raise RuntimeError(DEVICE_NOT_FOUND, device)
if DeviceCommonInstruction(instruction) is not None: if DeviceCommonInstruction(instruction) is not None:
# print('deviceCommonInstr')
# print(instruction)
device.call_instruction(instruction) device.call_instruction(instruction)
elif instruction in device.library.instruction_table: elif instruction in device.library.instruction_table:
# print('instruction')
# print(instruction)
device.call_instruction(instruction) device.call_instruction(instruction)
else: else:
raise RuntimeError(INSTRUCTION_UNKNOWN, instruction) raise RuntimeError(INSTRUCTION_UNKNOWN, instruction)
+187 -115
View File
@@ -1,6 +1,7 @@
import abc import abc
import struct import struct
import math import math
import numpy
from typing import Optional, TypeVar, Generic, Tuple, Dict, List, AnyStr from typing import Optional, TypeVar, Generic, Tuple, Dict, List, AnyStr
from datetime import datetime from datetime import datetime
@@ -853,7 +854,7 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp', __slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
'_total_time_stamp', '_mode', '_cycle_start_time', '_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop') '_mode_stop', '_show_data')
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@@ -868,6 +869,8 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
self._mode = 0 self._mode = 0
self._cycle_start_time = [] self._cycle_start_time = []
self._show_data = False
@property @property
def name(self) -> str: def name(self) -> str:
return self.NAME return self.NAME
@@ -881,16 +884,24 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
def decode(self, data: bytes) -> Optional[RecordingData]: def decode(self, data: bytes) -> Optional[RecordingData]:
if len(data) < 18: if len(data) < 18:
return None return None
voltage = 0
mem_cnt = data[1]
time_stamp: float = struct.unpack('<I', data[4:8])[0] # unit: ms 0x18030000
current = struct.unpack('<i', data[8:12])[0] # unit: nA
voltage = struct.unpack('<i', data[12:16])[0] # unit: uV
impedance = struct.unpack('<i', data[16:20])[0] # unit: mOm
time_stamp: float = struct.unpack('<I', data[1:5])[0] # unit: ms 0x18030000 cycle_number = struct.unpack('<H', data[20:22])[0]
current = struct.unpack('<i', data[5:9])[0] # unit: nA finish_mode_falg = data[22]
voltage = struct.unpack('<i', data[9:13])[0] # unit: uV battery = struct.unpack('<i', data[23:27])[0]
impedance = struct.unpack('<i', data[13:17])[0] # unit: mOm elite_notify_times = data[27]
cycle_number = struct.unpack('<H', data[17:19])[0] notify_one = struct.unpack('<i', data[28:32])[0]
finish_mode_falg = data[19] notify_two = struct.unpack('<i', data[32:36])[0]
notify_three = struct.unpack('<i', data[36:40])[0]
# self._show_data = True
mem_wrong_information = struct.unpack('<i', data[40:40+4])[0] # mem_wrong_information = green retry, green wrong, red retry, red wrong mem_wrong_information = struct.unpack('<i', data[43:47])[0] # mem_wrong_information = green retry, green wrong, red retry, red wrong
ram_num = data[44] ram_num = data[47]
broken_flag = data[-1] broken_flag = data[-1]
if (finish_mode_falg & 0b11110000 == 0b10100000): if (finish_mode_falg & 0b11110000 == 0b10100000):
@@ -911,9 +922,11 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
print("error timeStamp full data:", list(data), datetime.now(), '\n') print("error timeStamp full data:", list(data), datetime.now(), '\n')
return None return None
else: else:
# print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2), if self._show_data:
# '|', current, '|', voltage, '|', impedance, print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
# '|', cycle_number, '|', finishMode, '@', str(self.device)) '|', current, '|', voltage, '|', impedance, '|', cycle_number,
'|', notify_one, '|', notify_two, '|', notify_three,
'|', finishMode, '@', str(self.device))
# print('|', '{:10}'.format(time_stamp), # print('|', '{:10}'.format(time_stamp),
# '|', '{:4}'.format(delta), # '|', '{:4}'.format(delta),
@@ -942,15 +955,21 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
ret.append_data(1, voltage) ret.append_data(1, voltage)
ret.append_data(2, impedance) ret.append_data(2, impedance)
ret.append_data(3, cycle_number) ret.append_data(3, cycle_number)
ret.append_data(4, notify_one)
ret.append_data(5, notify_two)
ret.append_data(6, notify_three)
# ret.append_data(4, battery)
# ret.append_data(5, elite_notify_times)
# ret.append_data(6, mem_cnt)
# memoryboard information # # memoryboard information
ret.append_data(4, ram_num) # ret.append_data(7, ram_num)
ret.append_data(5, broken_flag) # ret.append_data(8, broken_flag)
try: # try:
ret.append_data(6, mem_wrong_information) # ret.append_data(9, mem_wrong_information)
# print('append_data success, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information)) # # print('append_data success, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
except: # except:
print('append_data fail, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information)) # print('append_data fail, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
@@ -1327,8 +1346,8 @@ class EISZeroOneDataDecoder(RecDataDecoder):
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp', __slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
'_total_time_stamp', '_mode', '_cycle_start_time', '_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff', '_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff',
'cali_coeff', '_ac_amp', '_mode', '_freq_start', '_freq_stop', 'cali_coeff', '_ac_amp', '_mode',
'_freq_direction', '_last_phase', '_first_phase_flag') '_last_phase', '_first_phase_flag', '_show_data')
def __init__(self, cali_coeff: bytes = None): def __init__(self, cali_coeff: bytes = None):
super().__init__() super().__init__()
@@ -1343,15 +1362,14 @@ class EISZeroOneDataDecoder(RecDataDecoder):
self._cycle_start_time = [] self._cycle_start_time = []
self._ac_amp: int = 0 self._ac_amp: int = 0
self._mode: int = 0 self._mode: int = 0
self._freq_start: int = 0
self._freq_stop: int = 0
self._freq_direction = 0
self._last_phase = 0 self._last_phase = 0
self._first_phase_flag = 1 self._first_phase_flag = 1
self._cali_coeff: Optional[bytes] = None self._cali_coeff: Optional[bytes] = None
self.cali_coeff: Optional[List[Tuple[int, int]]] = None self.cali_coeff: Optional[List[Tuple[int, int]]] = None
self._show_data = False
if cali_coeff is not None: if cali_coeff is not None:
self._cali_coeff = cali_coeff self._cali_coeff = cali_coeff
self.cali_coeff = self._decode_cali_coeff(cali_coeff) self.cali_coeff = self._decode_cali_coeff(cali_coeff)
@@ -1360,12 +1378,27 @@ class EISZeroOneDataDecoder(RecDataDecoder):
def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]: def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]:
if cali_coeff != b'': if cali_coeff != b'':
cali_table = [] cali_table = []
phase_para_a = []
phase_para_b = []
hsrtia_a = [] hsrtia_a = []
hsrtia_b = [] hsrtia_b = []
hsrtia_c = [] hsrtia_c = []
hsrtia_d = [] hsrtia_d = []
phase_coeff = []
phase_offset = []
# phase_coeff = [[0]*4 for i in range(4)]
# phase_offset = [[0]*4 for i in range(4)]
phase_coeff = numpy.zeros([4, 4], dtype = int)
phase_offset = numpy.zeros([4, 4], dtype = int)
########################################
# phase_coeff
# [[gain0, g1, g2, g3] ----->最高頻
# [gain0, g1, g2, g3] ----->中頻
# [gain0, g1, g2, g3] ----->低頻
# [gain0, g1, g2, g3] ----->最低頻
# ]
#######################################
# print('cali_coeff', cali_coeff) # print('cali_coeff', cali_coeff)
cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4 cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4
@@ -1376,57 +1409,95 @@ class EISZeroOneDataDecoder(RecDataDecoder):
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4 # hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
index = 20 index = 20
for i in range(index, index+16, 8): g = 0
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0]) phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0]) phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 40 index = 40
for i in range(index, index+16, 8): g = 0
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0]) phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0]) phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
#Lv[0] 160k #Lv[0] 160k
index = 60 index = 60
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8) hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8) hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4) hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
#Lv[1] 20k #Lv[1] 20k
index = 80 index = 80
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8) hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8) hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4) hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
#Lv[2] 5k #Lv[2] 5k
index = 100 index = 100
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8) hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8) hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4) hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
#Lv[3] 200R #Lv[3] 200R
index = 120 index = 120
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8) hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8) hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4) hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
# hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0]) index = 140
# hsrtia_b.append(struct.unpack('>I', cali_coeff[index+5:index+9])[0]/1e6) g = 1
# hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e5) phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
# hsrtia_d.append(struct.unpack('>I', cali_coeff[index+13:index+17])[0]/1e6) phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 160
g = 1
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 180
g = 2
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 200
g = 2
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 220
g = 3
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
index = 240
g = 3
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
# print('cutoff_freq', cutoff_freq) # print('cutoff_freq', cutoff_freq)
# print('hsrtia_a', hsrtia_a) # print('hsrtia_a', hsrtia_a)
# print('hsrtia_b', hsrtia_b) # print('hsrtia_b', hsrtia_b)
# print('hsrtia_c', hsrtia_c) # print('hsrtia_c', hsrtia_c)
# print('hsrtia_d', hsrtia_d) # print('phase_coeff')
# print('phase_para_a', phase_para_a) # print(phase_coeff)
# print('phase_para_b', phase_para_b) # print('phase_offset')
# print(phase_offset)
cali_table.append((cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d)) cali_table.append((cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
return cali_table return cali_table
else: else:
@@ -1450,13 +1521,13 @@ class EISZeroOneDataDecoder(RecDataDecoder):
if len(data) < 18: if len(data) < 18:
return None return None
ch1 = struct.unpack('>i', data[1:5])[0] # unit: 1/1000 nA ch1 = struct.unpack('>i', data[1+3:5+3])[0] # unit: 1/1000 nA
ch2 = struct.unpack('>i', data[5:9])[0] # unit: mV ch2 = struct.unpack('>i', data[5+3:9+3])[0] # unit: mV
ch3 = struct.unpack('>i', data[9:13])[0] # unit: kOm ch3 = struct.unpack('>i', data[9+3:13+3])[0] # unit: kOm
time_stamp: float = struct.unpack('<I', data[13:17])[0] # unit: ms time_stamp: float = struct.unpack('<I', data[13+3:17+3])[0] # unit: ms
cycle_number = struct.unpack('>H', data[17:19])[0] cycle_number = struct.unpack('>H', data[17+3:19+3])[0]
d19 = data[19] d19 = data[19+3]
gain = (d19 & 0x0F) gain = data[20+3]
finishMode = (d19 & 0x80) >> 7 finishMode = (d19 & 0x80) >> 7
if time_stamp == 0: if time_stamp == 0:
@@ -1476,30 +1547,31 @@ class EISZeroOneDataDecoder(RecDataDecoder):
return None return None
else: else:
if self.cali_coeff is not None and self._mode == 0: if self.cali_coeff is not None and self._mode == 0:
phase_para_a = []
phase_para_b = []
hsrtia_a = [] hsrtia_a = []
hsrtia_b = [] hsrtia_b = []
hsrtia_c = [] hsrtia_c = []
hsrtia_d = [] hsrtia_d = []
cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0] cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
voltage_amp = round(self._ac_amp * 800 / 2047) # use UI value voltage_amp = round(self._ac_amp * 800 / 2047) # use UI value
if (self._freq_start > self._freq_stop):
self._freq_direction = 0
else:
self._freq_direction = 1
if (self._mode == 0): if (self._mode == 0):
img = ch1 img = ch1
real = ch2 real = ch2
freq = ch3 freq = ch3
fre_idx = 0
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2) rolloff_cali = cutoff_freq/1e5
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / rolloff_cali ** 2 / 1e4)
# if (gain == 3): # if (gain == 3):
# current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag) # current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag)
# else: # else:
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain]
# current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
# print(current) # print(current)
# print(voltage_mag) # print(voltage_mag)
# print(hsrtia_a[gain]) # print(hsrtia_a[gain])
@@ -1512,64 +1584,64 @@ class EISZeroOneDataDecoder(RecDataDecoder):
else: else:
impedance = 0 impedance = 0
if (real > 0): raw_phase = math.atan2(img , real) * 180 / math.pi
raw_phase = math.atan(img / real) * 180 / math.pi
elif (real == 0):
raw_phase = 90
else:
raw_phase = math.atan(img / real) * 180 / math.pi + 180
if (freq >= 1000000): # 10000 Hz if (freq >= 1000000): # 10000 Hz
i = 0 fre_idx = 0
elif (freq >= 10000): # 100 Hz elif (freq >= 10000): # 100 Hz
i = 1 fre_idx = 1
elif (freq >= 1000): # 10 Hz elif (freq >= 1000): # 10 Hz
i = 2 fre_idx = 2
elif (freq >= 1): # 0.01 Hz elif (freq >= 1): # 0.01 Hz
i = 3 fre_idx = 3
ideal_raw_phase = phase_para_a[i] /1e10 * freq + phase_para_b[i] / 1e6 ideal_raw_phase = phase_coeff[gain][fre_idx] /1e10 * freq + phase_offset[gain][fre_idx] / 1e6
phase = raw_phase - ideal_raw_phase phase = raw_phase - ideal_raw_phase
phase = phase % 180 if phase % 180<=90 else phase % 180-180
if (self._first_phase_flag): # last_phase_to90 = self._last_phase % 180 if self._last_phase % 180<=90 else self._last_phase % 180-180
self._last_phase = phase # diff = phase - last_phase_to90
self._first_phase_flag = 0
elif (abs(phase - self._last_phase) >= 200): # if (self._first_phase_flag):
phase -= 360 # # self._last_phase = phase
self._last_phase = phase # self._first_phase_flag = 0
# elif (abs(diff) >= 90):
# phase = self._last_phase + diff + (180 if diff<0 else-180)
# else:
# phase = self._last_phase + diff
# self._last_phase = phase
imag_after_cal = impedance * math.sin(round(phase) * math.pi / 180) imag_after_cal = impedance * math.sin(round(phase) * math.pi / 180)
real_after_cal = impedance * math.cos(round(phase) * math.pi / 180) real_after_cal = impedance * math.cos(round(phase) * math.pi / 180)
if self._show_data:
if (self._mode == 0): if (self._mode == 0):
# print('|', '{:10}'.format(time_stamp), print('|', '{:10}'.format(time_stamp),
# '|', '{:5}'.format(delta), '|', '{:5}'.format(delta),
# '|', '{:6}'.format(ch1), '|', '{:6}'.format(ch1),
# '|', '{:6}'.format(ch2), '|', '{:6}'.format(ch2),
# '|', '{:8}'.format(ch3 / 100), '|', '{:8}'.format(ch3 / 100),
# '|', '{:6}'.format(round(voltage_mag)), '|', '{:6}'.format(round(voltage_mag)),
# '|', '{:5}'.format(int(imag_after_cal)), '|', '{:5}'.format(int(imag_after_cal)),
# '|', '{:5}'.format(int(real_after_cal)), '|', '{:5}'.format(int(real_after_cal)),
# '|', '{:5}'.format(round(impedance)), '|', '{:5}'.format(round(impedance)),
# '|', '{:5}'.format(round(phase, 1)), '|', '{:5}'.format(round(phase, 1)),
# '|', '{:5}'.format(round(current, 3)), '|', '{:5}'.format(round(current, 3)),
# '|', '{:1}'.format(gain), '|', '{:1}'.format(gain),
# '|', '{:1}'.format(finishMode), '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|') '@', str(self.device), '|', flush = True)
pass pass
else: else:
# print('|', '{:10}'.format(time_stamp), print('|', '{:10}'.format(time_stamp),
# '|', '{:5}'.format(delta), '|', '{:5}'.format(delta),
# '|', '{:5}'.format(ch1), '|', '{:5}'.format(ch1),
# '|', '{:5}'.format(ch2), '|', '{:5}'.format(ch2),
# '|', '{:5}'.format(ch3), '|', '{:5}'.format(ch3),
# '|', '{:5}'.format(cycle_number), '|', '{:5}'.format(cycle_number),
# '|', '{:1}'.format(gain), '|', '{:1}'.format(gain),
# '|', '{:1}'.format(finishMode), '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|') '@', str(self.device), '|', flush = True)
pass pass
if finishMode == True: if finishMode == True:
print("finishMode full data:", list(data), datetime.now()) print("finishMode full data:", list(data), datetime.now())
@@ -1579,10 +1651,10 @@ class EISZeroOneDataDecoder(RecDataDecoder):
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0) ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
if (self._mode == 0): #EIS Mode if (self._mode == 0): #EIS Mode
ret.append_data(3, cycle_number)
ret.append_data(0, ch1) #Raw Imag ret.append_data(0, ch1) #Raw Imag
ret.append_data(1, ch2) #Raw Real ret.append_data(1, ch2) #Raw Real
ret.append_data(2, ch3 * 10) #Frequency [mHz] ret.append_data(2, ch3 * 10) #Frequency [mHz]
ret.append_data(3, cycle_number)
ret.append_data(4, round(imag_after_cal)) #Z_imag [Ohm] ret.append_data(4, round(imag_after_cal)) #Z_imag [Ohm]
ret.append_data(5, round(real_after_cal)) #Z_real [Ohm] ret.append_data(5, round(real_after_cal)) #Z_real [Ohm]
ret.append_data(6, round(impedance)) #Impedance [Ohm] ret.append_data(6, round(impedance)) #Impedance [Ohm]
@@ -1591,10 +1663,10 @@ class EISZeroOneDataDecoder(RecDataDecoder):
ret.append_data(9, gain) #Gain Level ret.append_data(9, gain) #Gain Level
else: #CV Mode else: #CV Mode
ret.append_data(3, cycle_number)
ret.append_data(0, ch1) #Iin [nA] ret.append_data(0, ch1) #Iin [nA]
ret.append_data(1, ch2) #Vset [nV] ret.append_data(1, ch2) #Vset [nV]
ret.append_data(2, ch3) #Vout [nV] ret.append_data(2, ch3) #Vout [nV]
ret.append_data(3, cycle_number)
if cycle_number != self._cycle_number: if cycle_number != self._cycle_number:
# notify cycle_number change # notify cycle_number change
-13
View File
@@ -651,17 +651,9 @@ class DeviceInstruction:
VIS_DEVICE_DONE = 0x20 VIS_DEVICE_DONE = 0x20
"""identify device done""" """identify device done"""
VIS_CC_ZERO = 0x40
VIS_ASK = 0x30
"""ask in virtual instruction"""
VIS_STI = 0xC0 VIS_STI = 0xC0
"""stimulation on virtual instruction""" """stimulation on virtual instruction"""
VIS_FUH = 0x90
"""flush virtual instruction"""
VIS_INT = 0x60 VIS_INT = 0x60
"""interrupt virtual instruction""" """interrupt virtual instruction"""
@@ -732,7 +724,6 @@ class DeviceCommonInstruction:
STOP_STIMULATE = "stop_stimulate" STOP_STIMULATE = "stop_stimulate"
VIS_DEVICE_DETECT = 'VIS_DEVICE_DETECT' VIS_DEVICE_DETECT = 'VIS_DEVICE_DETECT'
VIS_DEVICE_DONE = 'VIS_DEVICE_DONE' VIS_DEVICE_DONE = 'VIS_DEVICE_DONE'
VIS_CC_ZERO = 'VIS_CC_ZERO'
CIS_VOLT = 'CIS_VOLT' CIS_VOLT = 'CIS_VOLT'
CIS_VERSION = 'CIS_VERSION' CIS_VERSION = 'CIS_VERSION'
@@ -750,16 +741,12 @@ class DeviceCommonInstruction:
return '_sync(False)', '_notify(False)', 'VIS_INT' return '_sync(False)', '_notify(False)', 'VIS_INT'
elif instruction == cls.CLOSE: elif instruction == cls.CLOSE:
return '_sync(False)', '_notify(False)', 'VIS_INT' return '_sync(False)', '_notify(False)', 'VIS_INT'
elif instruction == cls.FLUSH:
return 'VIS_FUH',
elif instruction == cls.CALL: elif instruction == cls.CALL:
return 'VIS_CAL', return 'VIS_CAL',
elif instruction == cls.VIS_DEVICE_DETECT: elif instruction == cls.VIS_DEVICE_DETECT:
return 'VIS_DEVICE_DETECT', return 'VIS_DEVICE_DETECT',
elif instruction == cls.VIS_DEVICE_DONE: elif instruction == cls.VIS_DEVICE_DONE:
return 'VIS_DEVICE_DONE', return 'VIS_DEVICE_DONE',
elif instruction == cls.VIS_CC_ZERO:
return 'VIS_CC_ZERO',
elif instruction == cls.RECORD: elif instruction == cls.RECORD:
return 'VIS_STARTR', return 'VIS_STARTR',
elif instruction == cls.RECORD_ALL: elif instruction == cls.RECORD_ALL:
+15 -2
View File
@@ -4,6 +4,7 @@ from biopro.util.text import part_suffix
from . import * from . import *
from .expression import * from .expression import *
import json
class DeviceParameterError(RuntimeError): class DeviceParameterError(RuntimeError):
__slots__ = () __slots__ = ()
@@ -309,6 +310,8 @@ class ParameterValueDomain(ParameterDomain, metaclass=abc.ABCMeta):
return f return f
def valid_para(self, value: Any) -> bool: def valid_para(self, value: Any) -> bool:
if isinstance(value, list):
return True
f, t = self.range f, t = self.range
return f <= float(value) < t return f <= float(value) < t
@@ -489,8 +492,12 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
@classmethod @classmethod
def parse(cls, expr: Union[int, str]) -> 'ParameterCollectionValueOperator': def parse(cls, expr: Union[int, str]) -> 'ParameterCollectionValueOperator':
# parse epression then create value_operator
if isinstance(expr, int): if isinstance(expr, int):
return SingleValueOperator(None, expr) return SingleValueOperator(None, expr)
elif isinstance(expr, list):
return CollectValueOperator((0, len(expr)), expr)
elif expr == '*': elif expr == '*':
return AddAllValueOperator return AddAllValueOperator
@@ -498,6 +505,10 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
elif expr == ':=': elif expr == ':=':
return CollectValueOperator((None, None), []) return CollectValueOperator((None, None), [])
elif '[' in expr and ']' in expr:
v = json.loads(expr)
return CollectValueOperator((0, len(v)), v)
elif '=' in expr: elif '=' in expr:
a, v = part_suffix(expr, '=') a, v = part_suffix(expr, '=')
@@ -508,6 +519,7 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
return CollectValueOperator((None, None), v) return CollectValueOperator((None, None), v)
else: else:
# get list length (old way)
a, b = part_suffix(a, ':') a, b = part_suffix(a, ':')
a = int(a) if len(a) else None a = int(a) if len(a) else None
b = int(b) if len(b) else None b = int(b) if len(b) else None
@@ -602,8 +614,8 @@ class ParameterCollectionDomain(ParameterDomain, metaclass=abc.ABCMeta):
def __init__(self, domain: ParameterDomain): def __init__(self, domain: ParameterDomain):
super().__init__() super().__init__()
if isinstance(domain, ParameterCollectionDomain): # if isinstance(domain, ParameterCollectionDomain):
raise RuntimeError('cannot compose with parameter collection domain') # raise RuntimeError('cannot compose with parameter collection domain')
self._domain = domain self._domain = domain
@@ -725,6 +737,7 @@ class ParameterListDomain(ParameterCollectionDomain):
if oper == AddAllValueOperator: if oper == AddAllValueOperator:
raise ValueError("list parameter cannot accept '*' (all) value") raise ValueError("list parameter cannot accept '*' (all) value")
# d: domain, sz: lsit length, i: slice(a, b), v: list value
d = self.element_domain d = self.element_domain
sz = len(target) sz = len(target)
i = oper.index(sz) i = oper.index(sz)
+7 -3
View File
@@ -119,7 +119,10 @@ class DeviceConfigurationEncoder:
e.write(b'L\0') e.write(b'L\0')
else: else:
parameter_type = cls._value_type(value[0]) parameter_type = cls._value_type(max(value))
for v in value:
if isinstance(v, int) and v < 0:
parameter_type = parameter_type.lower()
e.write(b'L') e.write(b'L')
e.write(parameter_type.encode()) e.write(parameter_type.encode())
e.u8(sz) e.u8(sz)
@@ -153,7 +156,8 @@ class DeviceConfigurationEncoder:
if isinstance(value, bool): if isinstance(value, bool):
e.u8(1 if value else 0) e.u8(1 if value else 0)
elif isinstance(value, str): elif isinstance(value, str) or isinstance(value, list):
value = str(value)
e.encode_string(value) e.encode_string(value)
elif isinstance(value, int): elif isinstance(value, int):
@@ -170,7 +174,7 @@ class DeviceConfigurationEncoder:
if isinstance(value, bool): if isinstance(value, bool):
return '?' return '?'
elif isinstance(value, str): elif isinstance(value, str) or isinstance(value, list):
return 'p' return 'p'
elif isinstance(value, int): elif isinstance(value, int):
+4 -2
View File
@@ -1268,14 +1268,15 @@ class InstructionTable(DictNode['Instruction']):
instruction: str): instruction: str):
"""call instruction. chain context with :class:`DeviceInternalInstructionScope` """call instruction. chain context with :class:`DeviceInternalInstructionScope`
:param master: master device :param master: DeviceManager
:param device: device :param device: CompletedDevice
:param context: scope :param context: scope
:param instruction: instruction name :param instruction: instruction name
:raises InstructionNotFound: If instruction not found. :raises InstructionNotFound: If instruction not found.
""" """
try: try:
# ex. start
ins = self[instruction] ins = self[instruction]
except KeyError as e: except KeyError as e:
@@ -1284,6 +1285,7 @@ class InstructionTable(DictNode['Instruction']):
else: else:
context = context.chain(InstructionTableScope(self)) context = context.chain(InstructionTableScope(self))
# ex. _data_format, _sync, _notify
for single in ins.eval_instruction(context): for single in ins.eval_instruction(context):
if isinstance(single, InternalInstruction): if isinstance(single, InternalInstruction):
if not single.handle_internal_instruction(master, device, context): if not single.handle_internal_instruction(master, device, context):
+41 -6
View File
@@ -510,9 +510,10 @@ class DeviceParameter(JsonSerialize):
:param para: parameter name :param para: parameter name
:param oper: operator expression :param oper: operator expression
""" """
# parse operator return CollectValueOperator instance
if not isinstance(oper, ParameterCollectionValueOperator): if not isinstance(oper, ParameterCollectionValueOperator):
oper = ParameterCollectionValueOperator.parse(oper) oper = ParameterCollectionValueOperator.parse(oper)
table = self._library.parameter_table table = self._library.parameter_table
info = table[para] info = table[para]
domain = info.domain domain = info.domain
@@ -528,6 +529,7 @@ class DeviceParameter(JsonSerialize):
old = list(target) old = list(target)
try: try:
# replace target with new oper
domain.oper_para(target, oper, self._context) domain.oper_para(target, oper, self._context)
except RuntimeError as e: except RuntimeError as e:
raise IllegalParameterValueError(para, str(oper)) from e raise IllegalParameterValueError(para, str(oper)) from e
@@ -966,7 +968,7 @@ class CompletedDevice(Device):
""" """
__slots__ = ('_master', '_device_id', '_device', '_library', '_context', __slots__ = ('_master', '_device_id', '_device', '_library', '_context',
'_parameter', '_configuration', '_lock', '_feature_mask', '_parameter', '_configuration', '_lock', '_feature_mask',
'_cache_battery', '_cache_battery_timestamp', '_coeff') '_cache_battery', '_cache_battery_timestamp', '_coeff', '_status')
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device): def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
""" """
@@ -976,11 +978,15 @@ class CompletedDevice(Device):
:param device_id: device id :param device_id: device id
:param device: slave device implementation :param device: slave device implementation
""" """
# DeviceManager
self._master = master self._master = master
self._device = device self._device = device
self._device_id = device_id self._device_id = device_id
self._library = library self._library = library
# device status ( 0: idle, 1: working, 2: error, 3: power off)
self._status = 0
# context # context
s1 = library.constant s1 = library.constant
s2 = DeviceScope(self) s2 = DeviceScope(self)
@@ -1008,6 +1014,10 @@ class CompletedDevice(Device):
def device_id(self) -> int: def device_id(self) -> int:
return self._device_id return self._device_id
@property
def memory_board(self) -> int:
return self._device_id
@property @property
def device_name(self) -> str: def device_name(self) -> str:
return self._device.device_name return self._device.device_name
@@ -1020,6 +1030,10 @@ class CompletedDevice(Device):
def mac_address(self) -> ADDRESS: def mac_address(self) -> ADDRESS:
return self._device.mac_address return self._device.mac_address
@property
def mac_address_in_str(self) -> str:
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address).upper()
@property @property
def device(self) -> Device: def device(self) -> Device:
return self._device return self._device
@@ -1056,11 +1070,18 @@ class CompletedDevice(Device):
return self._library return self._library
# device lock # device lock
@property @property
def lock(self) -> DeviceLock: def lock(self) -> DeviceLock:
return self._lock return self._lock
@property
def status(self) -> int:
return self._status
@status.setter
def status(self, new_status):
self._status = new_status
# device parameter getter/setter # device parameter getter/setter
def parameters(self) -> List[str]: def parameters(self) -> List[str]:
@@ -1084,6 +1105,8 @@ class CompletedDevice(Device):
return self._configuration.get_parameter(name, False) return self._configuration.get_parameter(name, False)
def set_multi_parameters(self, parameter): def set_multi_parameters(self, parameter):
if len(parameter) == 0:
return
for (name, value) in parameter[0].items(): for (name, value) in parameter[0].items():
if name != 'target': if name != 'target':
self.set_parameter(name, value) self.set_parameter(name, value)
@@ -1107,6 +1130,11 @@ class CompletedDevice(Device):
self._parameter.set_parameter(name, value) self._parameter.set_parameter(name, value)
# raise RuntimeError('illegal parameter value : ' + value) from e # raise RuntimeError('illegal parameter value : ' + value) from e
else: else:
if name == 'MODE':
if self.library_name.startswith('Elite_EDC'):
self.set_parameter('CTRL_HIGH_Z_15', self.get_parameter('HIGHZ_TABLE')[value])
self.set_parameter('TIME_DURATION', 0)
self._parameter.set_parameter(name, value) self._parameter.set_parameter(name, value)
on_change = info.on_change on_change = info.on_change
@@ -1115,7 +1143,8 @@ class CompletedDevice(Device):
self._master.log_warn('on_change instruction not found : ' + on_change) self._master.log_warn('on_change instruction not found : ' + on_change)
else: else:
self.call_instruction(on_change) if self._status == 1:
self.call_instruction(on_change)
# device instruction call # device instruction call
@@ -1258,14 +1287,20 @@ class CompletedDevice(Device):
def as_json(self) -> JSON_OBJECT: def as_json(self) -> JSON_OBJECT:
return { return {
'id': self.device_id,
'name': self.device_name,
'status': self._status,
'device_id': self.device_id, 'device_id': self.device_id,
'device_name': self.device_name, 'device_name': self.device_name,
'device_address': list(self.mac_address), 'device_address': list(self.mac_address),
'device_status': self._status,
'mac_address': self.mac_address_in_str,
'memory_board': self.memory_board,
'serial_number': self.serial_number.as_json(),
'version': self.device_version,
'battery': self.battery, 'battery': self.battery,
'parent': self.parent, 'parent': self.parent,
'recording_file_name': self.recording_file_name, 'recording_file_name': self.recording_file_name,
'device_version': self.device_version,
'serial_number': self.serial_number.as_json(),
'library_name': self._library.name, 'library_name': self._library.name,
'library_version': str(self._library.version), 'library_version': str(self._library.version),
'configuration': self.configuration.as_json(list_hide=True), 'configuration': self.configuration.as_json(list_hide=True),
+87 -48
View File
@@ -35,7 +35,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
'_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value', '_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value',
'_read_green_times','_read_red_times', '_read_green_times','_read_red_times',
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len', '_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
'_head_wrong_cnt') '_head_wrong_cnt', '_pin_busy_value')
def __init__(self, def __init__(self,
select: Selector, select: Selector,
@@ -46,15 +46,15 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
self._elite_data_len = 40 self._elite_data_len = 40
self._mem_header_len = 3 self._mem_header_len = 3
self._mem_tailer_len = 8 self._mem_tailer_len = 6
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
# buffer # buffer
self._tx_buffer_header = [0] * 19 self._tx_buffer_header = [0] * 64
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3) self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
# memory control pin # memory control pin
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True) self.pin_busy: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_BZY)
self.pin_mem_req = OutputPin.get_used(P3Pin.MEM_REQ, False) self.pin_mem_req = OutputPin.get_used(P3Pin.MEM_REQ, False)
self.pin_mem_sel = OutputPin.get_used(P3Pin.MEM_RST, True) # MEM_RST -> actually which memory board is assign self.pin_mem_sel = OutputPin.get_used(P3Pin.MEM_RST, True) # MEM_RST -> actually which memory board is assign
self.pin_ram_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL) # MEM_SEL -> actually is RAM_SEL, which RAM is assign self.pin_ram_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL) # MEM_SEL -> actually is RAM_SEL, which RAM is assign
@@ -62,6 +62,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
self._pin_ram_sel_value = [bool(self.pin_ram_sel) for _ in range(Selector.SIZE)] self._pin_ram_sel_value = [bool(self.pin_ram_sel) for _ in range(Selector.SIZE)]
self._pin_mem_sel_value = [bool(self.pin_mem_sel) for _ in range(Selector.SIZE)] self._pin_mem_sel_value = [bool(self.pin_mem_sel) for _ in range(Selector.SIZE)]
self._pin_mem_req_value = [bool(self.pin_mem_req) for _ in range(Selector.SIZE)] self._pin_mem_req_value = [bool(self.pin_mem_req) for _ in range(Selector.SIZE)]
self._pin_busy_value = [bool(self.pin_busy) for _ in range(Selector.SIZE)]
self._read_green_times = 0 self._read_green_times = 0
self._read_red_times = 0 self._read_red_times = 0
@@ -76,6 +77,8 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
def set_pin_mem_req(self, value: bool): def set_pin_mem_req(self, value: bool):
channel = self.select channel = self.select
# if self._pin_mem_req_value[channel] == value:
# print('last_req_sig[channel] == value', channel, self._pin_mem_req_value[channel], value, datetime.now())
self.pin_mem_req.output(value) self.pin_mem_req.output(value)
self._pin_mem_req_value[channel] = value self._pin_mem_req_value[channel] = value
@@ -96,6 +99,14 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
self._pin_ram_sel_value[channel] = True self._pin_ram_sel_value[channel] = True
return self._pin_ram_sel_value[channel] return self._pin_ram_sel_value[channel]
def get_pin_busy(self):
channel = self.select
if self.pin_busy.input() == 0:
self._pin_busy_value[channel] = False
else:
self._pin_busy_value[channel] = True
return self._pin_busy_value[channel]
@property @property
def select(self) -> int: def select(self) -> int:
return self._selector.channel return self._selector.channel
@@ -167,10 +178,33 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
print("read red data times", self._read_red_times) print("read red data times", self._read_red_times)
return data return data
def _compare_green_data_addr_and_flag(self, data: Union[bytes, List[int]], device: int):
green_data_section1 = data[3:7]
green_data_section2 = data[7:11]
green_data_section3 = data[11:15]
green_data_section = []
if green_data_section1 == green_data_section2:
green_data_section = green_data_section1
elif(green_data_section2 == green_data_section3 or green_data_section1 == green_data_section3):
print("green data not equal: = ", data[3:15])
print("green data print:", data, device, datetime.now())
green_data_section = green_data_section3
else:
print("green data not equal: = ", data[3:15])
print("green data print:", data, device, datetime.now())
green_data_section = green_data_section3 # use last data
return green_data_section
def _print_ram_all_data(self): def _print_ram_all_data(self):
addr = 0 addr = 0
red_length = int(7000 / 2) red_length = int(7000 / 2)
tx_temp = [0] * red_length tx_temp = [0] * (red_length + 3)
while True: while True:
tx_temp[0] = MEM_INS_READ tx_temp[0] = MEM_INS_READ
@@ -191,7 +225,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
return return
def recv_memory(self, device: int) -> Optional[bytes]: def recv_memory(self, device: int) -> Optional[bytes]:
self.pin_busy.output(False) # self.pin_busy.output(False)
# print('mem_req==ram_sel,[', self._pin_mem_req_value[device], ',', self._pin_ram_sel_value[device], ']')
rx = [] rx = []
@@ -216,7 +252,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1 self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
if (self._head_wrong_cnt[device] <= 5): # print 5 times if (self._head_wrong_cnt[device] <= 5): # print 5 times
print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times') print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
print(list(data[0:15])) print(list(data))
data[0:3] = [255, 255, 255] data[0:3] = [255, 255, 255]
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
@@ -235,13 +271,13 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1 # self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
# if (self._head_wrong_cnt[device] < 10): # if (self._head_wrong_cnt[device] < 10):
# print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times') # print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
# print(list(data_first[0:7])) # print(list(data_first))
# if (data_second[0] != 255 or data_second[1] != 255 or data_second[2] != 255): # if (data_second[0] != 255 or data_second[1] != 255 or data_second[2] != 255):
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1 # self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
# if (self._head_wrong_cnt[device] < 10): # if (self._head_wrong_cnt[device] < 10):
# print('data_second[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times') # print('data_second[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
# print(list(data_second[0:7])) # print(list(data_second))
# if (data_first[3:] == data_second[3:]): # if (data_first[3:] == data_second[3:]):
# data = data_first # data = data_first
@@ -253,27 +289,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
# data = self.compare_green_data(data_first, data_second, data_third, len(tx_h)) # data = self.compare_green_data(data_first, data_second, data_third, len(tx_h))
# ---------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------
# debug use green_data_section = self._compare_green_data_addr_and_flag(data, device)
# green_data = []
# green_data = data
# print("_[Debug] @ spi green data = ", green_data)
green_data_section1 = data[3:7]
green_data_section2 = data[7:11]
green_data_section3 = data[11:15]
if green_data_section1 == green_data_section2:
green_data_section = green_data_section1
elif(green_data_section2 == green_data_section3 or green_data_section1 == green_data_section3):
print("green data not equal: = ", data[3:15])
print("green data print:", data, device, datetime.now())
green_data_section = green_data_section3
else:
print("green data not equal: = ", data[3:15])
print("green data print:", data, device, datetime.now())
green_data_section = green_data_section3 # use last data
length = (green_data_section[0] << 8) | green_data_section[1] length = (green_data_section[0] << 8) | green_data_section[1]
header = data[15] header = data[15]
@@ -284,8 +300,8 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
print("length < 12") print("length < 12")
print("green data print:", data, device, datetime.now()) print("green data print:", data, device, datetime.now())
if length == 0: # if length == 0:
self._print_ram_all_data() # self._print_ram_all_data()
return None return None
@@ -295,6 +311,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
print("green data print:", data, device, datetime.now()) print("green data print:", data, device, datetime.now())
return None return None
# print('data=', list(data))
# print('Ram:', data[62])
if (length >= 4000): if (length >= 4000):
flag_print = True flag_print = True
print("green data: big length:", length) print("green data: big length:", length)
@@ -302,7 +321,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
if (header != 255): if (header != 255):
flag_print = True flag_print = True
print("green data: header is not 255: ", header) print("green data: header is not 255: ", header)
self._print_ram_all_data() # self._print_ram_all_data()
if (elite_data_len != self._elite_data_len): if (elite_data_len != self._elite_data_len):
flag_print = True flag_print = True
@@ -311,18 +330,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
if (flag_print): if (flag_print):
print("green data print:", data, device, datetime.now(), '\n') print("green data print:", data, device, datetime.now(), '\n')
# neulive
# address += len(data) - 11
# tx_d = self._tx_buffer_data
# red_length = len(tx_d)
address = 12 address = 12
red_length = int(length / 2) red_length = int(length / 2)
tx_d = [0] * red_length tx_d = [0] * (red_length + 3)
# elite read len(_tx_buffer_data) byte
# address = 12
# tx_d = self._tx_buffer_data
while True: while True:
tx_d[0] = MEM_INS_READ tx_d[0] = MEM_INS_READ
@@ -377,11 +387,40 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
# * red data formate: # * red data formate:
# * ramHdr, ramHdr, ramHdr, (3B) # * ramHdr, ramHdr, ramHdr, (3B)
# * 255, #, data_length, (3B) # * 255, #, data_length, (3B)
# * data, (20B) # * data, (40B)
# * red_wrong, red_retry_cnt, green_wrong, green_retry_cnt, (4B) # * red_wrong, red_retry_cnt, green_wrong, green_retry_cnt, (4B)
# * 255, #, data_length, (3B) # * check_num, (1B)
# * */ # * */
# read again if check num is wrong
index = 0
check_number_print = False
for i in range(0, len(rx), self._single_data_len):
check_sum = sum(rx[i : i + self._single_data_len - 1]) & 0b11111111
# print(check_sum, rx[i + self._single_data_len - 1])
if (check_sum != rx[i + self._single_data_len - 1]):
# print('check_sum wrong, origin value:', 'check_sum =', check_sum, rx[i : i + self._single_data_len])
tx_d = [0] * (self._single_data_len + 3)
address = 12 + self._single_data_len * index
tx_d[0] = MEM_INS_READ
tx_d[1] = ((address >> 8) & 0xFF)
tx_d[2] = (address & 0xFF)
data = []
data = self._spi.send_byte(tx_d)
data[0:3] = [255, 255, 255]
rx[i : i + self._single_data_len] = data[3:]
print('check_sum wrong, read again:', 'check_sum =', check_sum, rx[i : i + self._single_data_len])
check_number_print = True
index = index + 1
if check_number_print:
print('check_sum wrong:', device, datetime.now())
for i in range(0, len(rx), self._single_data_len):
print(rx[i:i+self._single_data_len])
print()
# mark read # mark read
self._spi.send_byte(self.MEM_INS_MARKED1) self._spi.send_byte(self.MEM_INS_MARKED1)
self._spi.send_byte(self.MEM_INS_MARKED2) self._spi.send_byte(self.MEM_INS_MARKED2)
@@ -390,9 +429,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
except BaseException as e: except BaseException as e:
print(e) print(e)
finally: # finally:
# print("\n") # # print("\n")
self.pin_busy.output(True) # self.pin_busy.output(True)
return bytes(rx) return bytes(rx)
+1 -1
View File
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
self._serial = serial.Serial(self._port, self._serial = serial.Serial(self._port,
baudrate=self._baudrate, baudrate=self._baudrate,
timeout=0, timeout=0,
writeTimeout=0.01) writeTimeout=1)
# deprecate function name which change at version 3.0 # deprecate function name which change at version 3.0
self._serial.flushInput() self._serial.flushInput()
self._serial.flushOutput() self._serial.flushOutput()
+4 -4
View File
@@ -118,13 +118,13 @@ class Selector:
self._p2.output(p[2]) self._p2.output(p[2])
# if (value == 4 and self._last_sel != 6): # if (value == 4 and self._last_sel != 6):
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel) # print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
# elif (value == 5 and self._last_sel != 4): # elif (value == 5 and self._last_sel != 4):
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel) # print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
# elif (value == 7 and self._last_sel != 5): # elif (value == 7 and self._last_sel != 5):
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel) # print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
# elif (value == 6 and self._last_sel != 7): # elif (value == 6 and self._last_sel != 7):
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel) # print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
self._last_sel = value self._last_sel = value
+27 -58
View File
@@ -1,65 +1,34 @@
class Action(): class Action():
def __init__(self, task, action_id, action): def __init__(self, action_id, action):
self._task = task self._id: str = action_id
self._id:str = action_id self._type: str = action['type']
self._type:str = action['type'] self._target: str = action['target']
self._target:str = action['target'] self._condition : list[str] = action['condition']
self._condition_list:list[str] = action['condition'] # self._duration = action.get('duration', None)
self._duration = action.get('duration', None) # self._goto = action.get('goto', None)
self._goto = action.get('goto', None) # self._cycle = action.get('cycle', None)
self._cycle = action.get('cycle', None)
self._instruction = None
self.update_instruction()
@property
def id(self):
return self._id
@property @property
def type(self): def type(self):
return self._type return self._type
def update_instruction(self): @property
self._instruction = { def target(self):
"device_instruction": { return self._target
"header": "call_instruction",
"device": self._target, @property
"arguments": { def condition(self):
"instruction": self._type, return self._condition
}
}, def as_json(self):
"device_parameter": { return {
"header": "set_multi_parameters", 'id': self._id,
"device": self._target, 'type': self._type,
"arguments": { 'target': self._target,
"parameter": self._task.get_parameter_set_by_device(self._target), 'condition': self._condition
}
},
"device_recording_file_name": {
"header": "update_recording_file_name_info",
"device": self._target,
"arguments": {
"content": self._task.file_name,
}
},
"device_parent": {
"header": "update_parent_info",
"device": self._target,
"arguments": {
"content": self._task.parent
}
}
} }
def get_condition_list(self):
return self._condition_list
def get_instruction(self, value):
return self._instruction[value]
def get_instruction_list(self):
instruction_set = {
'start': ['device_parent', 'device_recording_file_name', 'device_parameter', 'device_instruction'],
'stop': ['device_instruction'],
}
return map(self.get_instruction, instruction_set[self._type])
+99 -29
View File
@@ -3,73 +3,143 @@ from time import time
class Condition(): class Condition():
def __init__(self, id, condition): def __init__(self, id, condition):
print('condition', id, condition)
self._id = id self._id = id
self._type = condition['type'] self._type = condition['type']
self._comparsion = condition['comparsion'] self._comparsion = condition['comparsion']
self._value = condition['value'] self._value = condition['value']
self._active = False
@property @property
def id(self): def id(self):
return self._id return self._id
@property @property
def type(self): def type(self):
return self._type return self._type
@property @property
def comparsion(self): def comparsion(self):
return self._comparsion return self._comparsion
@property @property
def value(self): def value(self):
return self._value return self._value
def set_comparsion(self, comparsion): @id.setter
self._comparsion = comparsion def id(self, new_id):
self._id = new_id
def set_type(self, type):
self._type = type
def set_value(self, value): @type.setter
self._value = value def type(self, new_type):
self._type = new_type
def compareWith(self, operator:str, x, y) -> bool: @comparsion.setter
def comparsion(self, new_comparsion):
self._comparsion = new_comparsion
@value.setter
def value(self, new_value):
self._value = new_value
def compareWith(self, operator, x, y) -> bool:
# print(operator, x, y)
cases = { cases = {
"equal": lambda a, b: a == b, "equal": lambda a, b: a == b,
"bigger": lambda a, b: a > b, "bigger": lambda a, b: a >= b,
"smaller": lambda a, b: a < b, "smaller": lambda a, b: a <= b,
} }
# print('x','y',x, y,type(x),type(y))
return cases[operator](x, y) return cases[operator](x, y)
def match_or_not(self, **kwargs): def match_or_not(self, **kwargs):
return self.method_mapping(self.type)() # print(self._type, self._comparsion, self._value)
return getattr(self, self.type)(**kwargs)
def absolute_time(self, **kwargs): def absolute_time(self, **kwargs):
now = time() # now = int(time())
time_condition = self.datetime_to_timestamp(self.str_to_datetime(self._value)) now = round(time(), 1)
time_condition = round(self.datetime_to_timestamp(self.str_to_datetime(self._value)))
return self.compareWith(self.comparsion, int(now), int(time_condition)) return self.compareWith(self.comparsion, now, time_condition)
def relative_time(self, **kwargs): def after_project_run(self, **kwargs):
now = time() project_start_time = kwargs['project_start_time']
delay_time = kwargs['delay_time']
# time_diff = int(time() - project_start_time - delay_time)
time_diff = round(time() - project_start_time - delay_time, 1)
return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
def after_task_run(self, **kwargs):
# print('relative_time_from_task', kwargs['task_start_time'],kwargs['delay_time'])
if len(kwargs['task_start_time']) == 0:
return False
task = kwargs['self_task']
running_task = kwargs['running_task']
task_start_time = kwargs['task_start_time'][-1]
delay_time = kwargs['delay_time']
time_diff = round(time() - task_start_time - delay_time, 1)
# print('real_diff', time() - task_start_time - delay_time)
# print(task.name, task.uuid, time_diff, round(int(self._value), 1), running_task.name, running_task.uuid)
# if round(int(self._value), 1) == 0 and time_diff == 0.1:
# return True
if task.uuid != running_task.uuid:
return False
return self.compareWith('bigger', time_diff, round(int(self._value), 1))
# return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
def device(self, **kwargs): def device(self, **kwargs):
print('device') print('device')
def task_status(self, **kwargs): """ def previous_task_done(self, **kwargs):
print('task_status') running_task = kwargs['running_task']
if running_task.status == 2 and self._active == False:
self._active = True
return True
return False """
def method_mapping(self, method_name): def previous_task_done(self, **kwargs):
methods = { running_task = kwargs['running_task']
"relative_time": self.relative_time, self_task = kwargs['self_task']
"absolute_time": self.absolute_time, # if running_task != None and self_task != None:
"device": self.device, # print('\nprevious_task_done: ', running_task.status, ' ', self._active)
"task_status": self.task_status, if running_task != self_task:
} if running_task == None:
return methods[method_name] return True
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False
def until_button_trigger(self, **kwargs):
running_task = kwargs['running_task']
if running_task != None:
if running_task.button_trigger == True:
running_task.button_trigger = False
return True
return False
""" def cycle(self, **kwargs):
running_task = kwargs['running_task']
self_task = kwargs['self_task']
if running_task != self_task:
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False """
def str_to_datetime(self, time_str): def str_to_datetime(self, time_str):
return datetime.strptime(time_str,'%Y-%m-%dT%H:%M') return datetime.strptime(time_str,'%Y-%m-%dT%H:%M')
def datetime_to_timestamp(self, date): def datetime_to_timestamp(self, date):
return datetime.timestamp(date) return datetime.timestamp(date)
def as_json(self):
return {
'id': self._id,
'type': self._type,
'comparsion': self._comparsion,
'value': self._value,
'active': self._active
}
+37
View File
@@ -0,0 +1,37 @@
class Instruction():
def __init__(self):
self._instruction_set = {
'set_file_name': {
'method': 'update_recording_file_name_info',
'arguments': ['file_name']
},
'set_parent': {
'method': 'update_parent_info',
'arguments': ['parent']
},
'set_parameter':{
'method': 'set_multi_parameters',
'arguments': ['parameter']
},
'call_instruction': {
'method': 'call_instruction',
'arguments': ['instruction']
},
}
self._start_instruction = list(map(lambda ins: self._instruction_set[ins] ,['set_file_name', 'set_parent', 'set_parameter', 'call_instruction']))
self._stop_instruction = list(map(lambda ins: self._instruction_set[ins] ,['call_instruction']))
self._idle_instruction = []
@property
def start(self) -> list:
return self._start_instruction
@property
def stop(self) -> list:
return self._stop_instruction
@property
def idle(self) -> list:
return self.idle_instruction
+288 -42
View File
@@ -1,78 +1,324 @@
from .task import Task
from .task_manager import TaskManager
import sys import sys
import json import json
import threading import threading
import time
from time import time, sleep
from datetime import datetime from datetime import datetime
from collections import deque from collections import deque
from copy import copy
from uuid import uuid4
from .task import Task
from .task_manager import TaskManager
from .instruction import Instruction
from biopro.device.manager import DeviceManager from biopro.device.manager import DeviceManager
from biopro.text import * from biopro.text import *
key_list = {
'deviceList': 'device',
}
class Project(threading.Thread): class Project(threading.Thread):
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, name="project"): def __init__(self, project, device_manager: DeviceManager, mqttThread = None, log_verbose = None, name="project"):
super(Project, self).__init__(name = name) super(Project, self).__init__(name = name)
self._project = project self._project = project
self._device_manager = device_manager self._device_manager = device_manager
self._mqtt_thread = mqttThread self._mqtt_thread = mqttThread
self._time_interval = 1 self._time_interval = 0.1
self._start_time = None self._start_time = None
self._end_time = None
self._task_manager = TaskManager(self._project['taskList']) self._id = None
self._uuid = str(uuid4())
self._name = None
self._desc = None
self._device = None
self._complete_device = {}
self._status = 0
self._instruction_set = Instruction()
self._stop_flag = False
self._task_manager = None
self._cycle = []
self._count = 1 #流水號
self.log_verbose = log_verbose
self.setup_project(project)
self.setup_device(self._device)
def setup_project(self, project):
for (key, value) in project.items():
if key in key_list.keys():
key = key_list[key]
if key == 'task':
self._task_manager = TaskManager(project['task'], project['cycle'])
elif key == 'uuid':
pass
else:
setattr(self, key, value)
def setup_device(self, device_list):
for device in device_list:
mac_address = device_list[device]['pair']
complete_device = self._device_manager.get_device(mac_address)
self._complete_device[device] = complete_device
@property
def id(self) -> int:
return self._id
@id.setter
def id(self, new_id):
self._id = new_id
@property
def uuid(self) -> str:
return self._uuid
@uuid.setter
def uuid(self, new_uuid):
self._uuid = new_uuid
@property
def name(self) -> str:
return self._name
@name.setter
def name(self, new_name):
self._name = new_name
@property
def cycle(self) -> list:
return self._cycle
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
self._start_time = None
@property @property
def desc(self) -> str: def desc(self) -> str:
return self._project['desc'] return self._desc
@desc.setter
def desc(self, new_desc):
self._desc = new_desc
@property @property
def status(self) -> str: def status(self) -> str:
return self._project['status'] return self._status
@status.setter
def status(self, new_status):
self._status = new_status
@property @property
def device(self) -> list: def device(self) -> list:
return self._project['deviceList'] return self._device
@device.setter
def device(self, new_device):
self._device = new_device
@property
def task_list(self):
return self._task_manager.export_task_list
@property @property
def task(self) -> list: def mqtt_thread(self):
return self._task_manager.get() return self._mqtt_thread
@property @property
def get_current_task(self) -> str: def running_task(self):
return self._task_manager.get_current_task() return self._task_manager.running_task
def run(self): def run(self):
self._start_time = time.time() self._status = 1
self._start_time = time()
self.log_verbose('Project ' + self.name + ' start')
self.mqtt_thread.broadcast_command('project:' + self._name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
while not self._stop_flag :
# check running task first
delay_time = 0
check_list = copy(self._task_manager.check_list)
while True: for task in check_list:
# current task if task != None:
for task in self._task_manager.get_check_task_list(): now = time()
# [<match_condition>, ...]
match_condition_list = task.check_condition('time')
# [[<match_action>, ...], ...]
match_action_list = task.get_match_action_list(match_condition_list)
for action_list in match_action_list:
for action in action_list:
if action.type == 'start':
self._task_manager.set_current_task(task)
task.do_action(action)
while len(task.instruction_list) > 0:
instruction = task.instruction_list.pop(0)
if instruction.get('device', None) != None:
device = self._device_manager.get_device(self.device[instruction['device']]['connectDevice']['device_address'])
if device is None: match_condition_list = task.check_condition(
raise RuntimeError(DEVICE_NOT_FOUND, device) project_start_time = self._start_time,
delay_time = delay_time,
# print(instruction['header'], *instruction['arguments'].values()) running_task= self._task_manager.running_task,
getattr(device, instruction['header'])(*instruction['arguments'].values()) previous_task = self._task_manager.prev_task,
self_task = task
)
for condition in match_condition_list:
match_action_list = task.get_match_action(condition.id)
for action in match_action_list:
if action.type == 'cycle' and condition.type == 'previous_task_done':
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._task_manager.set_running_task(task)
if action.type == 'cycle' and condition.type == 'until_button_trigger':
self._task_manager.running_task.stop()
if self._task_manager.running_task != None:
if self._task_manager.running_task.uuid == task.uuid and action.type == 'cycle' and condition.type == 'after_task_run':
self._task_manager.running_task.stop()
if action.type == 'start':
if task.status != 1:
self._task_manager.set_running_task(task)
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# elif action.type == 'stop':
# self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# self._count += 1
# if self.check_running_task_not_run() == True:
# self._task_manager.running_task.stop()
elif action.type == 'idle':
self._task_manager.running_task.stop()
instruction_set = None
if action.target is not None:
device = self._complete_device[action.target]
if ((action.type == 'start' and device.status == 0) or (action.type == 'stop' and device.status == 1)):
self.log_verbose('Project' + self.name + 'Task ' + task.name + ' match_condition ' + condition.type + ' trigger_action ' + action.type + ' ' + str(action.target))
task_info = task.get_task_info(action)
instruction_set = getattr(self._instruction_set, action.type, None)
# 檔名修正
# device
task_info['file_name'] += '#' + device.mac_address_in_str[12:].upper()
# 流水號
task_info['file_name'] += '#' + str(self._count)
# 添加cycle資訊
if len(self.cycle) > 0:
index = self._task_manager.get_index_by_task(task)
# get list of cycle determine by index of task
filtered = list(filter(lambda info: self._task_manager.get_index_by_uuid(info['range'][0]) < index and self._task_manager.get_index_by_uuid(info['range'][1]) > index, self.cycle))
if len(filtered) == 0:
pass
elif len(filtered) == 1:
if filtered[0]['useID'] == True:
task_info['file_name'] += '#' + str(filtered[0]['id'])
else:
task_info['file_name'] += '#' + str(filtered[0]['name']) + '-' + str(filtered[0]['count'])
else:
# if multi cycle, then sort by range from task index to cycle start index, then loop concat filename
filtered.sort(key=lambda info: abs(self._task_manager.get_index_by_uuid(info['range'][0]) - index))
for cycle_info in filtered:
if cycle_info['useID'] == True:
task_info['file_name'] += '#' + str(cycle_info['id'])
else:
task_info['file_name'] += '#' + str(cycle_info['name']) + '-' + str(cycle_info['count'])
self.log_verbose('file name ' + task_info['file_name'])
if instruction_set != None and len(task.parameter_set) > 0:
if action.type == 'start':
self._count += 1
for instruction in instruction_set:
print('instruction 1', device, instruction, datetime.now())
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
target=getattr(device, instruction['method'])(*args)
print('instruction 2', device, instruction, datetime.now())
delay_time += (time() - now)
# check task not running then stop
if self.check_running_task_not_run() == True:
if self._task_manager.running_task.type == '':
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._task_manager.running_task.stop()
# check project done then close project
if self.check_project_done() == True:
print('project stop at', datetime.now())
self.close()
if self._time_interval - delay_time > 0:
sleep(self._time_interval - delay_time)
def pause(self):
# TODO
pass
time.sleep(self._time_interval)
def stop(self): def stop(self):
return self._task_manager.running_task.stop()
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._status = 2
self._end_time = time()
self._stop_flag = True
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
def close(self): def close(self):
return self._status = 2
self._end_time = time()
self._stop_flag = True
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
def check_project_done(self):
for task in self._task_manager.task_list:
# if task never start or still task is running then reject
if task.status == 1 or task.status == -1:
return False
return True
def set_content(self, content):
self.running_task.button_trigger = True
def set_cycle(self, index, content):
# change cycle name
for key in content:
self.cycle[index][key] = content[key]
# change task name
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][0]).name = content['name']
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][1]).name = content['name']
def check_running_task_not_run(self):
# if no running task
if self._task_manager.running_task == None:
return False
# if running is cycle then no need to stop by device
if self._task_manager.running_task.type == 'cycle':
return False
for key in self._task_manager.running_task.action:
# print('action key', key, self._task_manager.running_task, self._task_manager.running_task.action[key])
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'stop':
return False
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'idle':
return False
for device in self._task_manager.running_task.device:
if self._complete_device[device].status == 1:
return False
return True
def as_json(self):
running_task = None
if self._task_manager.running_task is not None:
running_task = self._task_manager.running_task.as_json()
data = {
'id': self._id,
'name': self._name,
'uuid': self._uuid,
'desc': self._desc,
'status': self._status,
'device': self._device,
'task': self.task_list,
'running_task': running_task,
'cycle': self._cycle
}
return data
+23 -8
View File
@@ -9,25 +9,40 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':')) return _json_stringify(o, separators=(',', ':'))
class ProjectManager(): class ProjectManager():
def __init__(self, device_manager: DeviceManager, mqtt_thread=None) : def __init__(self, device_manager: DeviceManager, mqtt_thread=None, log_verbose = None) :
self._project_list = [] self._project_list = []
self._mqtt_thread = mqtt_thread self._mqtt_thread = mqtt_thread
self._device_manager = device_manager self._device_manager = device_manager
self.log_verbose = log_verbose
def create(self, project): def create(self, project):
new_project = Project(project, self._device_manager, self._mqtt_thread) new_project = Project(project, self._device_manager, self._mqtt_thread, self.log_verbose)
self._project_list.append(new_project) self._project_list.append(new_project)
return new_project return new_project
def remove(self, index): def remove(self, index):
self._project_list[index].stop() self._project_list[index].stop()
del self._project_list[index] del self._project_list[index]
def get(self): def get(self, project_uuid = None):
return self._project_list if project_uuid == None:
return self._project_list
else:
for project in self._project_list:
if project.uuid == project_uuid:
return project
def run(self, project): def run_project(self, project):
project.start() project.start()
def stop(self, project): def stop_project(self, project):
project.stop() _project = self.get(project)
_project.stop()
def set_project(self, project_uuid, content):
_project = self.get(project_uuid)
_project.set_content(content)
def set_project_cycle(self, project_uuid, index, content):
_project = self.get(project_uuid)
_project.set_cycle(index, content)
+261 -117
View File
@@ -1,110 +1,238 @@
from typing import List
from .condition import Condition from .condition import Condition
from .action import Action from .action import Action
from time import time from time import time
from datetime import datetime
key_list = {
'deviceList': 'device',
'parameterSet': 'parameter_set'
}
class Task: class Task:
def __init__(self, task): def __init__(self, task):
self._task = task self._id = None
self._uuid = None
self._condition_list = [] self._type = None
self._action_list = [] self._name = None
self._parent = None
self._start_time = time() self._cycle = None
self._idle_time = [] self._cycle_count = 0
self._period = None self._cycle_next = None
self._next_time = None self._cycle_next_uuid = None
self._last_time = None self._device = None
self._event = None
self._trigger = None
self._parameter_set = None
self._condition = None
self._action = None
# -1: init 0: start(idle), 1: run, 2: close(idle)
self._status = 0
self._next = None
# action & condition info
self._condition_list: List[Condition] = []
self._action_list: List[Action] = []
self._instruction_list = [] self._instruction_list = []
self._record_list = []
self.setup() # time info
self._start_time = []
self._idle_time = []
self._end_time = []
self._period = None
# trigger info
self._button_trigger = False
self.load_task(task)
def setup(self) -> None: def load_task(self, task) -> None:
# add condition # update task attribute
for key, condition in self._task['condition'].items(): for key, value in task.items():
new_condition = Condition(key, condition) if key in key_list.keys():
self._condition_list.append(new_condition) key = key_list[key]
if key == 'condition':
self.update_condition_list(value)
if key == 'action':
self.update_action_list(value)
# print(key, value)
setattr(self, key, value)
# add action def update_condition_list(self, condition_dict):
for key, action in self._task['action'].items(): self._condition_list.clear()
new_action = Action(self, key, action) for key, condition in condition_dict.items():
self._action_list.append(new_action) self._condition_list.append(Condition(key, condition))
def update_action_list(self, action_dict):
self._action_list.clear()
for key, action in action_dict.items():
self._action_list.append(Action(key, action))
@property @property
def id(self) -> str: def id(self) -> str:
return self._task['id'] return self._id
@property @id.setter
def file_name(self): def id(self, new_id):
return self._task['name'] self._id = new_id
@property
def parent(self):
return self._task.get('parent', {"folder": [2]})
@property
def instruction_list(self):
return self._instruction_list
@property
def cycle(self) -> int:
return self._task['cycle']
@property
def order(self) -> int:
return self._task['order']
@property
def max_cycle(self) -> int:
return self._task['max_cycle']
@property
def devices(self) -> dict:
return self._task['devices']
@property
def devices_id(self) -> list:
return [device_id for device_id in self.devices]
@property
def events(self) -> list:
return self._task['events']
@property
def triggers(self) -> list:
return self._task['triggers']
@property
def parameter_set(self) -> list:
return self._task['parameterSet']
@property
def instructions(self) -> list:
return self._task['instructions']
@property
def conditions(self) -> list:
return self._task['conditions']
@property
def actions(self) -> list:
return self._task['actions']
@property
def condition_list(self) -> list:
return self._condition_list
@property
def status(self) -> str:
return self._task['status']
@property @property
def uuid(self) -> str: def uuid(self) -> str:
return self._task['uuid'] return self._uuid
@uuid.setter
def uuid(self, new_uuid):
self._uuid = new_uuid
@property
def type(self):
return self._type
@type.setter
def type(self, new_type):
self._type = new_type
@property
def name(self):
return self._name
@name.setter
def name(self, new_name):
self._name = new_name
@property
def parent(self):
if self._parent == None:
return {"folder": [2]}
return self._parent
@parent.setter
def parent(self, new_parent):
self._parent = new_parent
@property
def cycle(self) -> int:
return self._cycle
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
# TODO: not sure needed?
@property
def cycle_count(self) -> int:
return self._cycle_count
@cycle_count.setter
def cycle_count(self, new_cycle_count):
self._cycle_count = new_cycle_count
@property
def cycle_next(self) -> str:
return self._cycle_next
@cycle_next.setter
def cycle_next(self, new_cycle_next):
self._cycle_next = new_cycle_next
@property
def cycle_next_uuid(self) -> str:
return self._cycle_next_uuid
@cycle_next_uuid.setter
def cycle_next_uuid(self, new_cycle_next_uuid):
self._cycle_next_uuid = new_cycle_next_uuid
@property
def device(self) -> dict:
return self._device
@device.setter
def device(self, new_device):
self._device = new_device
@property
def event(self) -> list:
return self._event
@event.setter
def event(self, new_event):
self._event = new_event
@property
def trigger(self) -> list:
return self._trigger
@trigger.setter
def trigger(self, new_trigger):
self._trigger = new_trigger
@property
def parameter_set(self) -> list:
return self._parameter_set
@parameter_set.setter
def parameter_set(self, new_parameter_set):
self._parameter_set = new_parameter_set
@property
def condition(self) -> list:
return self._condition
@condition.setter
def condition(self, new_condition):
self._condition = new_condition
@property
def action(self) -> list:
return self._action
@action.setter
def action(self, new_action):
self._action = new_action
@property
def status(self) -> str:
return self._status
@status.setter
def status(self, new_status):
self._status = new_status
@property @property
def next(self) -> str: def next(self) -> str:
return self._task['next'] return self._next
@next.setter
def next(self, new_next):
self._next = new_next
@property
def instruction_list(self) -> List:
return self._instruction_list
@property
def start_time(self) -> List:
return self._start_time
@property
def end_time(self) -> List:
return self._end_time
@property
def button_trigger(self) -> List:
return self._button_trigger
@button_trigger.setter
def button_trigger(self, button_trigger):
self._button_trigger = button_trigger
def new_start_time(self):
self._start_time.append(time())
def new_end_time(self):
self._end_time.append(time())
def get_parameter_set_by_device(self, device): def get_parameter_set_by_device(self, device):
return [parameter_set for parameter_set in self.parameter_set.values() if device == parameter_set['target']] return [parameter_set for parameter_set in self.parameter_set.values() if device == parameter_set['target']]
@@ -121,48 +249,64 @@ class Task:
return '|'.join(name_list) if name_or_value == 'name' else '|'.join(value_list) return '|'.join(name_list) if name_or_value == 'name' else '|'.join(value_list)
def run(self): def run(self):
self._status = 'running' print(self._name, 'run at', datetime.now())
self._start_time = time() self._status = 1
self._start_time.append(time())
def pause(self):
self._status = 'pause'
def set_cycle(self, cycle):
self._cycle = cycle
def set_status(self, status):
self._status = status
def start(self): def start(self):
self.set_status('running') self.status = 1
def stop(self): def stop(self):
if self.status == 'running': self.status = 2
self.do_action('stop')
self.set_status('idle')
def done(self):
self.set_status('done')
def end(self): def reset(self):
self.set_status('end') self.status = -1
# self.status = 0
def get_match_action_list(self, match_condition_list): def get_match_action_list(self, match_condition_list):
return map(lambda condition: [x for x in self._action_list if condition.id in x.get_condition_list()], match_condition_list) return map(lambda condition: [x for x in self._action_list if condition.id in x.get_condition_list()], match_condition_list)
def get_match_action(self, condition_id):
return [action for action in self._action_list if condition_id in action.condition]
def do_action(self, action): def do_action(self, action):
# # match_action = [x for x in self._action_list if condition_id in x.get_condition_list()]
# for action in match_action:
for instruction in action.get_instruction_list(): for instruction in action.get_instruction_list():
self._instruction_list.append(instruction) self._instruction_list.append(instruction)
def status_mapping(self, status): def check_condition(self, **kwargs):
statuses = { kwargs['task_start_time'] = self._start_time
"start": self.task_start, return [condition for condition in self._condition_list if condition.match_or_not(**kwargs)]
"done": self.task_done,
} def get_task_info(self, action):
return statuses[status] _type = action.type
if _type == 'stop':
_type = 'interrupt'
def check_condition(self, type): return {
return [condition for condition in self._condition_list if condition.match_or_not()] 'device': action.target,
'parameter': self.get_parameter_set_by_device(action.target),
'file_name': self._name,
'parent': self.parent,
'instruction': _type
}
def as_json(self):
return {
'id': self.id,
'name': self.name,
'parent': self.parent,
'type': self.type,
'uuid': self.uuid,
'cycle': self.cycle,
'cycle_count': self.cycle_count,
'cycle_next': self.cycle_next,
'cycle_next_uuid': self.cycle_next_uuid,
'device': self.device,
'event': self.event,
'trigger': self.trigger,
'parameter_set': self.parameter_set,
'condition': self.condition,
'action': self.action,
'status': self.status,
'next': self.next,
}
+131 -35
View File
@@ -1,5 +1,6 @@
from json import loads as json_parse, dumps as _json_stringify from json import loads as json_parse, dumps as _json_stringify
from typing import Dict, Optional, Any from socket import if_nametoindex
from typing import Dict, List, Optional, Any
from xml.dom.expatbuilder import parseString from xml.dom.expatbuilder import parseString
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from biopro.text import * from biopro.text import *
@@ -11,46 +12,141 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':')) return _json_stringify(o, separators=(',', ':'))
class TaskManager(): class TaskManager():
def __init__(self, task_list): def __init__(self, task_list, cycle_list):
self._current_task = None
self._task_list = [] self._task_list = []
self._need_to_check_task_list = [] self._next_task = []
self._prev_task = None
self._running_task = None
self._cycle_list = cycle_list
self.load_task_list(task_list)
# self.set_running_task(self._task_list[0])
# self._running_task.run()
self._next_task.append(self._task_list[0])
@property
def task_list(self):
return self._task_list
@property
def export_task_list(self):
return [d.as_json() for d in self._task_list]
@property
def prev_task(self):
return self._prev_task
@property
def running_task(self):
return self._running_task
@property
def next_task(self):
return self._next_task
def get_task_by_index(self, index):
return self._task_list[index]
def get_task_by_uuid(self, uuid):
return next((x for x in self.task_list if x.uuid == uuid), None)
def get_index_by_task(self, task):
return next((i for i, x in enumerate(self.task_list) if x.uuid == task.uuid), None)
def get_index_by_uuid(self, uuid):
return next((i for i, x in enumerate(self.task_list) if x.uuid == uuid), None)
def check_task_is_cycle_end(self, task):
for index, cycle in enumerate(self._cycle_list):
if cycle['range'][1] == task.uuid:
return index
@property
def check_list(self):
return [self._running_task, *self._next_task]
@property
def check_list(self):
return [self._running_task, *self._next_task]
def load_task_list(self, task_list):
for task in task_list: for task in task_list:
task = Task(task) task = Task(task)
self._task_list.append(task) self._task_list.append(task)
self.set_current_task(self._task_list[0])
self._current_task.run()
def remove(self, index): # original version
pass """ def set_running_task(self, task):
try:
# if there is task running & same task active ,then reject
if self._running_task != None and self._running_task.uuid == task.uuid:
return False
# save running task
self._prev_task = self._running_task
# clear next task list
self._next_task.clear()
self._running_task = task
self._running_task.run()
if self._prev_task != None:
# if previous task is still running, then need to close
if self._prev_task.status == 1:
self._prev_task.stop()
print('prev', 'run', self._prev_task.name, self._running_task.name)
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
self._next_task.append(_task)
except RuntimeError as e:
print(e) """
def set_running_task(self, task):
try:
# if there is task running & same task active ,then reject
if self._running_task != None and self._running_task.uuid == task.uuid:
return False
# save task
self._prev_task = self._running_task
# clear next task list
self._next_task.clear()
# set task to running_task
self._running_task = task
self._running_task.run()
# if previous task is still running, then need to close
if self._prev_task != None:
if self._prev_task.status == 1:
self._prev_task.stop()
# if reach cycle end, count < max, then go to cycle start
cycle_index = self.check_task_is_cycle_end(task)
if cycle_index is None:
# print('next', self._running_task.name, self._running_task.next)
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
# print('self._next_task', self._next_task)
else:
# print('cycle', self._cycle_list[cycle_index])
cycle = self._cycle_list[cycle_index]
if int(cycle['count']) < int(cycle['max']):
self._next_task.append(self.get_task_by_uuid(cycle['range'][0]))
cycle['count'] += 1
else:
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
cycle['count'] = 1
except RuntimeError as e:
print(e)
def get_task(self, task_id): def get_task(self, task_id):
return self._task_list[task_id] return self._task_list[task_id]
def get_check_task_list(self):
return self._need_to_check_task_list
def get_current_task(self) -> Task:
return self._current_task
def get_next_task(self):
return self._current_task.next
def set_current_task(self, task):
try:
if self._current_task != None and self._current_task.id != task.id:
self._current_task.stop()
self._current_task = task
self._need_to_check_task_list = []
# append current task
self._need_to_check_task_list.append(self._current_task)
# append next task
for task_uuid in self._current_task.next:
task = next((task for task in self._task_list if task.uuid == task_uuid), None)
self._need_to_check_task_list.append(task)
except Exception as e:
print(e)
+9 -6
View File
@@ -1131,14 +1131,17 @@ class RecordingFileWriter:
self._splitting_size = 0 self._splitting_size = 0
return None return None
def close(self): def close(self, mqtt_thread):
# if self._recording_file is not None:
# self._recording_file.close()
# self._recording_file = None
print('close1')
self._close = True self._close = True
if len(self._recording_file_dict) > 0: if len(self._recording_file_dict) > 0:
for ch in self._data_db.keys(): for ch in self._data_db.keys():
if len(self._data_rl[ch]) > 0:
self._data_rl[ch].append(str(int(self._time_now)))
mes = ' '.join(self._data_rl[ch])
mqtt_thread[ch].on_message(mes)
self._data_rl[ch].clear()
self._send_data[ch] = False
if self._recording_file_dict[ch]._status: if self._recording_file_dict[ch]._status:
_data = ' '.join(self._data_db[ch]) _data = ' '.join(self._data_db[ch])
self._raw_save['data'][ch] = _data self._raw_save['data'][ch] = _data
@@ -1315,7 +1318,7 @@ class RecordingFileWriter:
self._time_now = int(t) self._time_now = int(t)
return return
@calculate_time(1) # @calculate_time(1)
def write(self, data: Union[bytes, RecordingData, List[bytes], List[RecordingData]], mqtt_thread) -> int: def write(self, data: Union[bytes, RecordingData, List[bytes], List[RecordingData]], mqtt_thread) -> int:
# check size # check size
ths = self.splitting_threshold_size ths = self.splitting_threshold_size
+3 -17
View File
@@ -9,23 +9,9 @@ _jwt = None
def controller_device_id() -> str: def controller_device_id() -> str:
### device ID ### device ID
return 'b8:27:eb:52:ea:97' f = open("/sys/class/net/eth0/address", "r")
ret = None mac = f.read()[:-1]
try: return mac
with open('/etc/BPS/device_id') as f:
for line in f:
if line.startswith('#'):
continue
ret = line.strip()
break
except FileNotFoundError:
pass
if ret is None or len(ret) == 0:
return str(uuid.uuid1())
else:
return ret
def get_api_jwt() -> str: def get_api_jwt() -> str:
global _jwt global _jwt
+58 -34
View File
@@ -65,7 +65,7 @@ class DataServer(SocketServer, DataAPI):
""" """
global _FLAG_DATA_LOST_STATS_ global _FLAG_DATA_LOST_STATS_
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=3) super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=20)
data_options = DataServerOptions.get_options(*options) data_options = DataServerOptions.get_options(*options)
@@ -104,18 +104,9 @@ class DataServer(SocketServer, DataAPI):
self.log_verbose, self.log_verbose,
'MQTT-data-server') 'MQTT-data-server')
# api socket # api socket
self._queue_spi = queue.Queue()
# self._queue_spi_dict = {}
self._queue_ds_dict = {} self._queue_ds_dict = {}
self._queue_db = Queue() self._queue_db = Queue()
self._queue_db_error = Queue() self._queue_msg = Queue()
# self._queue_ds = Queue()
# if len(self._queue_spi_dict) == 0:
# self._queue_spi_dict[4] = Queue()
# self._queue_spi_dict[5] = Queue()
# self._queue_spi_dict[6] = Queue()
# self._queue_spi_dict[7] = Queue()
if len(self._queue_ds_dict) == 0: if len(self._queue_ds_dict) == 0:
self._queue_ds_dict[4] = Queue() self._queue_ds_dict[4] = Queue()
@@ -123,9 +114,12 @@ class DataServer(SocketServer, DataAPI):
self._queue_ds_dict[6] = Queue() self._queue_ds_dict[6] = Queue()
self._queue_ds_dict[7] = Queue() self._queue_ds_dict[7] = Queue()
self.database_process = DataBaseProcess('data_server', self.log_verbose, self._queue_db, self._queue_ds_dict, self._queue_db_error) self.database_process = DataBaseProcess('data_server', self.log_verbose, self._queue_db, self._queue_ds_dict, self._queue_msg)
self.database_process.start() self.database_process.start()
# self._no_data_total_duration = 0
# self._recv_memory_cost_time = 0
@logging_info @logging_info
def setup(self): def setup(self):
self._available_channel.clear() self._available_channel.clear()
@@ -146,7 +140,6 @@ class DataServer(SocketServer, DataAPI):
try: try:
self._stop_runtime() self._stop_runtime()
self.stop_sync() self.stop_sync()
self._queue_spi.queue.clear()
finally: finally:
self._configurations.clear() self._configurations.clear()
@@ -185,9 +178,6 @@ class DataServer(SocketServer, DataAPI):
self._configurations.clear() self._configurations.clear()
with CacheClient() as client:
client.clear()
# reopen spi, which has close at close() # reopen spi, which has close at close()
if spi_mode is None: if spi_mode is None:
spi_mode = self._spi_mode spi_mode = self._spi_mode
@@ -417,7 +407,7 @@ class DataServer(SocketServer, DataAPI):
c.join() c.join()
self._spi.set_wait_flag(c._device, True) self._spi.set_wait_flag(c._device, True)
data_runtime_process = RecordingProcess('data_server', self.log_verbose, device_id, data_runtime_process = RecordingProcess('data_server', self.log_verbose, device_id,
Queue(), self._queue_ds_dict[int(device_id)], meta_file, Queue(), self._queue_ds_dict[int(device_id)], self._queue_msg, meta_file,
json_stringify(_device), _parameter, _parent, _recording_file_name, json_stringify(_device), _parameter, _parent, _recording_file_name,
data_format, self.socket_mqtt_ip, self.socket_mqtt_port, data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
database = self.database_process ) database = self.database_process )
@@ -618,8 +608,18 @@ class DataServer(SocketServer, DataAPI):
return return
def open_cache_client(self): def open_cache_client(self):
self._cache_client = None self.log_verbose('open cache client')
return try:
client = CacheClient()
client.open_socket()
except RuntimeError as e:
self.log_warn(e)
else:
client.clear()
self._cache_client = client
def _ensure_cache_client(self) -> Optional[CacheClient]: def _ensure_cache_client(self) -> Optional[CacheClient]:
if self._cache_client is None: if self._cache_client is None:
@@ -646,6 +646,7 @@ class DataServer(SocketServer, DataAPI):
def whether_to_record(self, device): def whether_to_record(self, device):
# if user click "start", return True; if user click "stop", return False; # if user click "start", return True; if user click "stop", return False;
if device in self._configurations.keys() and self._configurations[device] is not None: if device in self._configurations.keys() and self._configurations[device] is not None:
# print(self._configurations.keys(), ',', device, datetime.now())
return True return True
else: else:
return False return False
@@ -654,6 +655,9 @@ class DataServer(SocketServer, DataAPI):
ret = False ret = False
sync = self.get_spi_obj() sync = self.get_spi_obj()
busy = sync.get_pin_busy()
# print('pin_busy=', busy, device, datetime.now())
if sync.get_pin_mem_req() == sync.get_pin_ram_sel(): if sync.get_pin_mem_req() == sync.get_pin_ram_sel():
spi_data = sync.recv_memory(device) spi_data = sync.recv_memory(device)
signal = sync.get_pin_mem_req() signal = sync.get_pin_mem_req()
@@ -662,29 +666,49 @@ class DataServer(SocketServer, DataAPI):
else: else:
data = None data = None
print('data=None, mem_req!=ram_sel, [', sync.get_pin_mem_req(), ', ', sync.get_pin_ram_sel(), ']', device, datetime.now())
if data is not None: if data is not None:
if self._configurations[device].queue_flag: if self._configurations.get(device, None) != None:
self._configurations[device].queue_flag = False if self._configurations[device].queue_flag:
print("q size= ", self._configurations[device]._queue_rec.qsize()) self._configurations[device].queue_flag = False
print("q size= ", self._configurations[device]._queue_rec.qsize())
self._configurations[device].put_rec_queue(data)
ret = True if self._configurations.get(device, None) != None:
self._configurations[device].put_rec_queue(data)
# self._no_data_total_duration = 0
ret = True
# else:
# time_diff = time() - self._recv_memory_cost_time
# self._no_data_total_duration += time_diff
# if self._no_data_total_duration > 1:
# print('data is None', device, datetime.now(), self._no_data_total_duration)
# print("sync.get_pin_mem_req() != sync.get_pin_ram_sel()")
# print("no~", sync.select, sync.get_pin_mem_req(), sync.get_pin_ram_sel(), datetime.now())
# print()
# self._recv_memory_cost_time = time()
return ret return ret
def rec_update(self) -> bool: def rec_update(self) -> bool:
ds_db_msg = self._queue_msg.get()
device_id = self._queue_db_error.get() with CacheClient() as client:
self.mqtt_thread.broadcast_command('runtime error: ' + str(device_id)) if isinstance(ds_db_msg, List):
content = { if ds_db_msg[0] == 'ds':
'header': 'device_instruction/0', client.send_command('device_instruction', ds_db_msg[1], ds_db_msg[2])
'device': device_id, else:
'instruction': 'interrupt' self.mqtt_thread.broadcast_command('runtime error: ' + str(ds_db_msg))
} content = {
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True) 'header': 'device_instruction/0',
'device': ds_db_msg,
'instruction': 'interrupt'
}
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True)
return True return True
def show_data(self, device):
self._configurations[device].put_rec_queue('show_data')
class DataRuntime(metaclass=abc.ABCMeta): class DataRuntime(metaclass=abc.ABCMeta):
__slots__ = ('_server', '_device', '_meta_file', '_data_format', __slots__ = ('_server', '_device', '_meta_file', '_data_format',
+6 -5
View File
@@ -69,7 +69,8 @@ class DataBaseProcess(Process):
self._data_raw_create_sql_str = None self._data_raw_create_sql_str = None
self._data_raw_update_sql_str = None self._data_raw_update_sql_str = None
self._data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s), end_time=%s, size=%s where id = %s' self._data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s) where id = %s'
self._new_data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s), end_time=%s, size=%s where id = %s'
self._data_mini_recording_sql_str = 'UPDATE "public"."%s_recording_data_minis" SET data_mean = concat(data_mean, %s) where id = %s' self._data_mini_recording_sql_str = 'UPDATE "public"."%s_recording_data_minis" SET data_mean = concat(data_mean, %s) where id = %s'
@property @property
@@ -160,7 +161,7 @@ class DataBaseProcess(Process):
getattr(self, do)(*args) getattr(self, do)(*args)
return None return None
@calculate_time(1) # @calculate_time(1)
def data_meta_write(self, _data: JSON_OBJECT, device_id, _uuid = None, _id = None): def data_meta_write(self, _data: JSON_OBJECT, device_id, _uuid = None, _id = None):
if _id > 0: if _id > 0:
sql_str = 'UPDATE "public"."recording_data_metas" SET ' sql_str = 'UPDATE "public"."recording_data_metas" SET '
@@ -376,7 +377,7 @@ class DataBaseProcess(Process):
print('recording error', e) print('recording error', e)
return None return None
@calculate_time(1) # @calculate_time(1)
def data_raw_recording_new(self, _id_dict, _channel_list, _data_dict, _end_time_dict, _size_dict): def data_raw_recording_new(self, _id_dict, _channel_list, _data_dict, _end_time_dict, _size_dict):
try: try:
para_list = [] para_list = []
@@ -384,7 +385,7 @@ class DataBaseProcess(Process):
para_list.append([_channel, _data_dict[_channel] + '"***"', _end_time_dict[_channel], _size_dict[_channel], _id_dict[_channel]]) para_list.append([_channel, _data_dict[_channel] + '"***"', _end_time_dict[_channel], _size_dict[_channel], _id_dict[_channel]])
with self._psql_conn as conn: with self._psql_conn as conn:
with conn.cursor() as sql_cursor: with conn.cursor() as sql_cursor:
execute_batch(sql_cursor, self._data_raw_recording_sql_str, para_list) execute_batch(sql_cursor, self._new_data_raw_recording_sql_str, para_list)
except psycopg2.Error as e: except psycopg2.Error as e:
print('recording error', e) print('recording error', e)
return None return None
@@ -446,7 +447,7 @@ class DataBaseProcess(Process):
return True return True
@calculate_time(1) # @calculate_time(1)
def data_mini_recording_new(self, _id_dict, _channel_list, _data_mean_dict): def data_mini_recording_new(self, _id_dict, _channel_list, _data_mean_dict):
try: try:
para_list = [] para_list = []
+52 -539
View File
@@ -43,7 +43,7 @@ def _fc(c):
return c % len(FORE_COLOR) + FORE_COLOR[0] return c % len(FORE_COLOR) + FORE_COLOR[0]
class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler): class ControlServer(SocketServer, ControlServerAPI):
"""Data Server""" """Data Server"""
def __init__(self, *options): def __init__(self, *options):
@@ -60,7 +60,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
:param options: server options :param options: server options
""" """
super().__init__((ControlAPI, CacheAPI), 'Controller', self.ADDR, super().__init__((ControlAPI), 'Controller', self.ADDR,
socket_listen=10, socket_listen=10,
thread_pool_count=16) thread_pool_count=16)
@@ -87,21 +87,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
data_options.repository = device_option.repository data_options.repository = device_option.repository
self.data_server = DataServerProcess(data_options) self.data_server = DataServerProcess(data_options)
# experimental protocol
# exp_options = ExpManagerOption.get_options(*options)
# self.exp_manager = ExpManager(self, exp_options)
# cache
self.cache_manager = CacheManager(self,
c.cache_server_cache_size,
# time unit from sec to ms
c.cache_server_cache_time * 1000)
# websocket server ###
### self.websocket_thread = WebsocketThread(self,
### c.websocket_address,
### c.websocket_port)
# remote server / MQTT # remote server / MQTT
self.mqtt_thread = None self.mqtt_thread = None
if not c.flag_disable_remote_server: if not c.flag_disable_remote_server:
@@ -112,17 +97,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
self.log_verbose, self.log_verbose,
'MQTT-control-server') 'MQTT-control-server')
# routine trash thread
self._routine_trash_thread = None
# if not c.flag_disable_routine_trash:
# self._routine_trash_thread = RoutineTrashThread(self._file_manager,
# c.trash_routine_time,
# c.trash_expire_time,
# c.trash_remove_expire_time)
# routine data routine
self._data_stream_thread = None
# LED control # LED control
self.led_thread = LEDControlThread(disable=c.flag_disable_led_control, self.led_thread = LEDControlThread(disable=c.flag_disable_led_control,
led_count=c.led_count, led_count=c.led_count,
@@ -131,6 +105,8 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
# device detect # device detect
self._detect_device_thread = RoutineConnectDeviceThread(self._device_manager, self.mqtt_thread, self.led_thread, 3) self._detect_device_thread = RoutineConnectDeviceThread(self._device_manager, self.mqtt_thread, self.led_thread, 3)
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread, self.log_verbose)
if not c.flag_disable_led_control: if not c.flag_disable_led_control:
self.led_thread.set_state(LED.COLOR_RED) self.led_thread.set_state(LED.COLOR_RED)
@@ -144,8 +120,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
self._session = {} self._session = {}
self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
# temp use variable
# indicate those device together # indicate those device together
self._device_instruction_group = None self._device_instruction_group = None
@@ -155,9 +129,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
# _api request build # _api request build
self._api = ApiRequests() self._api = ApiRequests()
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread)
# init method # init method
def _init_file_manager(self, option: ControlServerOptions) -> FileManager: def _init_file_manager(self, option: ControlServerOptions) -> FileManager:
@@ -249,32 +220,16 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
# device manager reset # device manager reset
self.submit_thread(self._setup_device) self.submit_thread(self._setup_device)
# self.submit_thread(self._setup_controller)
self._setup_controller() self._setup_controller()
# self.run_thread(self._detect_device_thread) # self.run_thread(self._detect_device_thread)
# experimental protocol manager
# if not self._controller_options.flag_disable_exp_manager:
# self.exp_manager.setup()
# self.exp_manager.reload_protocol()
# websocket server
### self.log_verbose('setup websocket server', pc(self.websocket_thread.websocket_address, YELLOW))
# websocket server thread run ###
### self.run_thread(self.websocket_thread)
# broadcast greeting # broadcast greeting
self.broadcast_command(DataMessage.greeting()) self.broadcast_command(DataMessage.greeting())
# routine trashing
if self._routine_trash_thread is not None:
self.run_thread(self._routine_trash_thread)
# remote server # remote server
if self.mqtt_thread is not None: if self.mqtt_thread is not None:
self.mqtt_thread.start() self.mqtt_thread.start()
# self.run_thread(self.mqtt_thread)
def _setup_file_manager(self): def _setup_file_manager(self):
self.log_verbose('setup file manager') self.log_verbose('setup file manager')
@@ -449,90 +404,14 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
self.broadcast_command('shutdown') self.broadcast_command('shutdown')
self.data_server.stop_process(external_interrupt) self.data_server.stop_process(external_interrupt)
self._stop_data_stream_thread()
self.device_manager.shutdown() self.device_manager.shutdown()
self.file_manager.shutdown(umount_external=True) self.file_manager.shutdown(umount_external=True)
self.cache_manager.shutdown()
### self.websocket_thread.close()
self.led_thread.close() self.led_thread.close()
if self.mqtt_thread is not None: if self.mqtt_thread is not None:
self.mqtt_thread.shutdown() self.mqtt_thread.shutdown()
# self.mqtt_thread.close()
# user session
def new_user_session(self) -> str:
session = UserSession(None)
self._session[session.user_session] = session
self.log_info('new user session', session.user_session)
return session.user_session
@logging_info
def del_user_session(self, user_session: Optional[str] = None):
if user_session is None:
self._session.clear()
else:
try:
del self._session[user_session]
except KeyError:
pass
def get_user_session(self,
user_session: Optional[str],
new_session = False,
allow_empty = False) -> Optional[UserSession]:
"""
:param user_session: user session ID
:param new_session: new a user session if *user_session* not found.
:param allow_empty: consider empty *user_session* None
:return: user session
"""
if user_session is None:
session = None
elif len(user_session) == 0:
if allow_empty:
session = None
else:
raise None
else:
session = self._session.get(user_session, None)
if session is not None:
session.time()
elif new_session:
session = UserSession(user_session)
self._session[session.user_session] = session
self.log_info('new user session', session.user_session)
return session
def expire_user_session(self):
current_time = time()
for user_session in list(self._session.keys()):
session = self._session[user_session]
if session.time(update=False) - current_time > self._user_session_expire:
del self._session[user_session]
# general post action
def _post_device_list(self) -> List[CompletedDevice]: def _post_device_list(self) -> List[CompletedDevice]:
"""general post action for getting list of connected devices. """general post action for getting list of connected devices.
@@ -869,12 +748,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
def get_device_info(self, device: int) -> Optional[CompletedDevice]: def get_device_info(self, device: int) -> Optional[CompletedDevice]:
return super().get_device_info(device) return super().get_device_info(device)
# @logging_info
# def device_call(self, device: int) -> bool:
# self.device_manager.call_device(device)
#
# return True
@logging_info @logging_info
def device_instruction_all(self, device: int) -> List[str]: def device_instruction_all(self, device: int) -> List[str]:
return self.device_manager.list_device_instruction(device) return self.device_manager.list_device_instruction(device)
@@ -946,12 +819,18 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
return True return True
@logging_info @logging_info
def device_battery(self) -> List[int]: def device_battery(self, device:int) -> List[int]:
device_list = self.device_manager.list_device() battery = {}
if len(device_list) > 0: if device == 'all':
battery_list = list(map(lambda x: self.device_manager.get_device(x).battery, device_list)) device_list = self.device_manager.list_device()
if len(device_list) > 0:
return battery_list battery = list(map(lambda x: {"device": x.memory_board, "battery":self.device_manager.get_device(x).battery}, device_list))
else:
battery = {
"device": device,
"battery": self.device_manager.get_device(device).battery
}
return battery
@logging_info @logging_info
def device_parent(self, device: int, content: Optional[str] = None) -> List[int]: def device_parent(self, device: int, content: Optional[str] = None) -> List[int]:
@@ -1048,8 +927,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
@logging_info @logging_info
def device_parameter(self, device: int, parameter: str, content: Optional[str] = None) -> Any: def device_parameter(self, device: int, parameter: str, content: Optional[str] = None) -> Any:
# if content is not None:
# self.broadcast_command('parameter:' + str(device) + '/' + parameter + '/' + content)
return self.device_manager.handle_device_parameter_command(device, parameter, content) return self.device_manager.handle_device_parameter_command(device, parameter, content)
@logging_info @logging_info
@@ -1141,255 +1018,35 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
def device_history_delete(self, user: str, device: Optional[int]) -> bool: def device_history_delete(self, user: str, device: Optional[int]) -> bool:
raise NotImplementedError() raise NotImplementedError()
# server provide method implement : file manager functions
@logging_info
def file_clean_storage(self) -> bool:
return super().file_clean_storage()
@logging_info
def file_index(self) -> RootInfo:
return super().file_index()
@logging_info
def file_list(self, path: str) -> DirectoryInfo:
return super().file_list(path)
@logging_info
def file_list_range(self, path: str, start: int, end: int) -> DirectoryInfo:
return super().file_list_range(path, start, end)
@logging_info
def file_rename(self, path: str, content: str) -> FileInfo:
return super().file_rename(path, content)
@logging_info
def file_mkdir(self, path: str) -> DirectoryInfo:
return super().file_mkdir(path)
@logging_info
def file_delete(self, path: str) -> bool:
return super().file_delete(path)
@logging_info
def file_info(self, path: str) -> FileInfo:
return super().file_info(path)
@logging_info
def file_meta_info(self, path: str) -> RecordingMetaFile:
return super().file_meta_info(path)
@logging_info
def file_export_info(self, path: str) -> Dict[str, Optional[Path]]:
return super().file_export_info(path)
@logging_info
def file_export_functions(self) -> Tuple[ExternalExportFunction, ...]:
return super().file_export_functions()
@logging_info
def file_export_parameters(self, ftype: str) -> Tuple[ExternalParameter, ...]:
return super().file_export_parameters(ftype)
@logging_info
def file_export(self, ftype: str, path: str, **options: str) -> str:
return super().file_export(ftype, path, **options)
@logging_info
def file_segment(self, method: str, path: str) -> Union[None, bool, FileSegment]:
return super().file_segment(method, path)
@logging_info
def file_segment_get(self, segment: int, path: str):
return super().file_segment_get(segment, path)
@logging_info
def file_handle_open(self, content: str) -> Optional[FileHandle]:
info = self.file_manager.info(content)
meta = info.meta_file
if meta is None:
raise RuntimeError('not a meta file')
handle = self.cache_manager.file_open(meta)
return self.file_handle_info(handle)
@logging_info
def file_handle_info(self, handle: int) -> Optional[FileHandle]:
info = self.cache_manager.file_info(handle)
if info is None:
return None
# modify file path
info.shadow_path(self.file_manager.shadow_path(Path(info.filepath)))
return info
@logging_info
def file_handle_close(self, handle: int):
self.cache_manager.file_close(handle)
@logging_info
def user_all(self) -> List[str]:
raise super().user_all()
@logging_info
def user_info(self, user: str, *, user_session: Optional[str] = None) -> Optional[AbstractUserSetting]:
return super().user_info(user, user_session=user_session)
@logging_info
def user_login(self, user: str, content: str, *,
user_session = None) -> ComplexResponse[AbstractUserSetting]:
raise super().user_login(user, content, user_session=user_session)
@logging_info
def user_logout(self, user_session: Optional[str] = None) -> None:
super().user_logout(user_session)
@logging_info
def user_add(self, user: str, content: str, *,
user_session = None) -> ComplexResponse[AbstractUserSetting]:
return super().user_add(user, content, user_session=user_session)
@logging_info
def user_del(self, user: str, content: str) -> bool:
return super().user_del(user, content)
@logging_info
def user_sync(self, user_session: Optional[str]) -> bool:
return super().user_sync(user_session)
@logging_info
def user_configuration_list(self, user_session: Optional[str], **options: str) -> List[str]:
return super().user_configuration_list(user_session, **options)
@logging_info
def user_configuration_get(self, name: str, user_session: Optional[str] = None) -> Optional[RecordingMetaFile]:
return super().user_configuration_get(name, user_session)
@logging_info
def user_configuration_add(self, name: str, content: str, user_session: Optional[str] = None) -> bool:
return super().user_configuration_add(name, content, user_session)
@logging_info
def user_configuration_del(self, name: str, user_session: Optional[str] = None) -> bool:
return super().user_configuration_del(name, user_session)
@logging_info
def user_configuration_clone(self, name: str, content: str, user_session: Optional[str] = None) -> bool:
return super().user_configuration_clone(name, content, user_session)
@logging_info
def user_setup_list(self, user_session: Optional[str] = None) -> List[str]:
return super().user_setup_list(user_session)
@logging_info
def user_setup_info(self, name: str, user_session: Optional[str] = None) -> Optional[UserSetup]:
return super().user_setup_info(name, user_session)
@logging_info
def user_setup_new(self, name: str, user_session: Optional[str] = None) -> Optional[UserSetup]:
return super().user_setup_new(name, user_session)
@logging_info
def user_setup_del(self, name: str, user_session: Optional[str] = None) -> bool:
return super().user_setup_del(name, user_session)
@logging_info
def user_alias_list(self, user_session: Optional[str] = None) -> List[UserDeviceAlias]:
return super().user_alias_list(user_session)
@logging_info
def user_alias_info(self, name: str, user_session: Optional[str] = None) -> Optional[UserDeviceAlias]:
return super().user_alias_info(name, user_session)
@logging_info
def user_alias_edit(self, name: str, content: str, user_session: Optional[str] = None) -> Optional[UserDeviceAlias]:
return super().user_alias_edit(name, content, user_session)
# @logging_info
# def exp_pro_list(self) -> List[ExpProtocolInfo]:
# return self.exp_manager.list_available_protocol()
@logging_info
def exp_pro_create(self, content: str, *,
user_session = None) -> int:
user_name = self._session_user_name(user_session)
if user_name is None:
raise RuntimeError('require user login')
self.file_manager.user_setting.user_info(user_name)
# p = self.exp_manager.create_protocol(content, user_name)
return
@logging_info @logging_info
def run_project(self, project) -> bool: def run_project(self, project) -> bool:
project = self._project_manager.create(project) if project is not None:
self._project_manager.run(project) # print(project)
return False project = self._project_manager.create(project)
self._project_manager.run_project(project)
return project.as_json()
@logging_info
def stop_project(self, project) -> bool:
if project is not None:
self._project_manager.stop_project(project)
return True
@logging_info
def set_project(self, project, content) -> bool:
if project is not None:
self._project_manager.set_project(project, content)
return True
@logging_info
def set_project_cycle(self, project, index, content) -> bool:
if project is not None:
self._project_manager.set_project_cycle(project, index, content)
return True
# @logging_info @logging_info
# def exp_pro_options(self, protocol: int) -> List[ExpOption]: def get_running_project(self) -> bool:
# return self.exp_manager.protocol_options(protocol) return self._project_manager.get()
# @logging_info
# def exp_pro_option(self, protocol: int, option: str, content: Optional[str] = None) -> bool:
# if content == '':
# # option reset
# if option == '':
# # reset all options
# self.exp_manager.protocol_reset(protocol)
# else:
# self.exp_manager.protocol_reset(protocol, *option.split(','))
# else:
# # option get/set
# self.exp_manager.protocol_option(protocol, option, content)
# return True
# @logging_info
# def exp_pro_status_all(self) -> List[AbstractExpProtocolState]:
# ret = []
# for p in self.exp_manager.list_protocol():
# s = self.exp_manager.protocol_status(p)
# if s is not None:
# ret.append(s)
# else:
# ret.append(AbstractExpProtocolState(p))
# return ret
# @logging_info
# def exp_pro_status(self, protocol: int) -> Optional[ExpProtocolState]:
# return self.exp_manager.protocol_status(protocol)
# @logging_info
# def exp_pro_command(self, protocol: int, content: str) -> bool:
# if content == 'ensure':
# return self.exp_manager.ensure_protocol(protocol)
# elif content == 'start':
# self.exp_manager.submit_protocol(protocol)
# elif content == 'interrupt':
# self.exp_manager.interrupt_protocol(protocol)
# elif content == 'suspend':
# self.exp_manager.suspend_protocol(protocol)
# elif content == 'resume':
# self.exp_manager.resume_protocol(protocol)
# else:
# raise RuntimeError('unknown protocol command : ' + content)
# return True
@logging_info @logging_info
def device_internal_command(self, device: int, oper: str, value: Any) -> bool: def device_internal_command(self, device: int, oper: str, value: Any) -> bool:
@@ -1406,8 +1063,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
return True return True
elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE: elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE:
if device is not None:
self._device_set_disable_cache(device, value)
return True return True
else: else:
@@ -1459,10 +1114,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
def _device_set_sync(self, device: CompletedDevice, sync: bool): def _device_set_sync(self, device: CompletedDevice, sync: bool):
if sync: if sync:
self.log_verbose('start sync', device.device_id)
self.cache_manager.drop_data(device)
client = self.data_server.client() client = self.data_server.client()
if client is not None: if client is not None:
info = self.file_manager.use(device) info = self.file_manager.use(device)
@@ -1473,22 +1124,14 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
filename = format_filename(self.TEMP_FILENAME_EXPR, device) filename = format_filename(self.TEMP_FILENAME_EXPR, device)
info = self.file_manager.save(device, filename) info = self.file_manager.save(device, filename)
client.update_device_configuration(device, info.meta_file, RawDataDecoder()) client.update_device_configuration(device, info.meta_file, RawDataDecoder())
print('***456')
if self._device_instruction_group is None: if self._device_instruction_group is None:
client.start_sync(device) client.start_sync(device)
if self._device_instruction_group is None: device.status = 1
# broadcast
self.broadcast_command(DataMessage.start(device.device_id))
else: else:
self.log_verbose('stop sync', device.device_id)
if self._device_instruction_group is None: if self._device_instruction_group is None:
start_sync = False start_sync = False
client = self.data_server.client() client = self.data_server.client()
if client is not None: if client is not None:
with client: with client:
@@ -1501,12 +1144,10 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
if start_sync: if start_sync:
# unset file info, but keep file path cache # unset file info, but keep file path cache
self.file_manager.unset(device.device_id) self.file_manager.unset(device.device_id)
device.status = 0
# broadcast
self.broadcast_command(DataMessage.stop(device.device_id))
# server provide method implement : websocket broadcast functions # server provide method implement : websocket broadcast functions
@logging_info @logging_info
def broadcast_command(self, command: str, device: Optional[int] = None): def broadcast_command(self, command: str, device: Optional[int] = None):
self.log_verbose(pc('broadcast_command', GREEN), self.log_verbose(pc('broadcast_command', GREEN),
@@ -1516,96 +1157,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
if self.mqtt_thread is not None: if self.mqtt_thread is not None:
self.mqtt_thread.broadcast_command(command, device=device) self.mqtt_thread.broadcast_command(command, device=device)
# data stream thread
def data_request_stream(self, start: bool, handler: DataMessageHandler):
if start:
t = self._start_data_stream_thread()
t.add_handle(handler)
else:
t = self._data_stream_thread
if t is not None:
t.del_handle(handler)
if not t.has_handle():
self._stop_data_stream_thread()
def _start_data_stream_thread(self) -> DataStreamThread:
t = self._data_stream_thread
if self._data_stream_thread is None:
self._data_stream_thread = t = self.run_thread(DataStreamThread(self))
return t
def _stop_data_stream_thread(self):
t = self._data_stream_thread
self._data_stream_thread = None
if t is not None:
t.close()
# noinspection PyShadowingNames
@logging_info
def websocket_command(self, command: str) -> Union[None, str, bytes, List[str]]:
if command == DataMessage.GREETING:
return DataMessage.greeting()
elif command == DataMessage.SYNC:
return self._websocket_command_sync(map(lambda d: d.device_id, self._post_device_list()))
elif command.startswith(DataMessage.SYNC):
_, device_list = part_suffix(command, ':')
if ',' in device_list:
return self._websocket_command_sync(map(int, device_list.split(',')))
else:
return self._websocket_command_sync([int(device_list)])
elif command.startswith(DataMessage.BROADCAST):
_, message = part_suffix(command, ':')
if message is not None:
self.broadcast_command(DataMessage.broadcast(message))
return None
# noinspection PyShadowingNames
def _websocket_command_sync(self, device_list: Iterable[int]) -> Union[str, List[str]]:
client = self.data_server.client()
if client is None:
return DataMessage.sync(False)
else:
result_start = []
result_stop = []
with client:
for device in device_list:
if client.is_sync(device):
result_start.append(device)
else:
result_stop.append(device)
return [DataMessage.start(result_start), DataMessage.stop(result_stop)]
# noinspection PyShadowingNames
def websocket_data_request(self, handler: DataMessageHandler, command: Optional[str]):
try:
self._handle_command_response(handler, command)
except (ValueError, IndexError) as e:
self.log_warn(e)
handler.on_error(DataMessage.warn(str(e)))
except BaseException as e:
self.log_warn(e)
handler.on_error(DataMessage.error(str(e)))
# noinspection PyShadowingNames # noinspection PyShadowingNames
def _handle_command_response(self, handler: DataMessageHandler, command: Optional[str]): def _handle_command_response(self, handler: DataMessageHandler, command: Optional[str]):
""" """
@@ -1627,29 +1178,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
else: else:
self.cache_manager.get_data_message(handler, response) self.cache_manager.get_data_message(handler, response)
# server provide method implement : cache API
@logging_verbose
def clear(self):
self.cache_manager.clear()
def push_data(self, data: Union[bytes, List[bytes]]):
self.cache_manager.push_data(data)
@logging_verbose
def drop_data(self, *device: int):
self.cache_manager.drop_data(*device)
def stop_data(self, device: int):
self.cache_manager.stop_data(device)
# noinspection PyShadowingNames
@logging_verbose
def notify_data(self, device: int, message: str):
self.broadcast_command(message, device=device)
# led function # led function
def get_led_state(self) -> str: def get_led_state(self) -> str:
return self.led_thread.state return self.led_thread.state
@@ -1657,7 +1186,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
self.led_thread.set_state(state) self.led_thread.set_state(state)
# hardware send test # hardware send test
if not _RUNTIME_COMPILE: if not _RUNTIME_COMPILE:
def _hardware_send_test(self, options: Dict[str, str]): def _hardware_send_test(self, options: Dict[str, str]):
@@ -1700,30 +1228,9 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
'export_root': str(self.file_manager.export_root) 'export_root': str(self.file_manager.export_root)
} }
if section is None or 'cache' in section:
ret['cache'] = {
'cache_size': self.cache_manager.cache_size,
'cache_time': self.cache_manager.cache_time,
}
# if section is None or 'websocket' in section:
# ret['websocket'] = {
# 'address': self.websocket_thread.websocket_address,
# 'port': self.websocket_thread.websocket_port,
# }
if section is None or 'mqtt' in section: if section is None or 'mqtt' in section:
ret['mqtt'] = None if self.mqtt_thread is None else self.mqtt_thread.hardware_test() ret['mqtt'] = None if self.mqtt_thread is None else self.mqtt_thread.hardware_test()
if section is None or 'trash' in section:
trash_manager = self._routine_trash_thread
ret['trash'] = None if trash_manager is None else {
'routine_interval': trash_manager.routine_interval,
'trash_expire': trash_manager.trash_expire,
'remove_expire': trash_manager.remove_expire,
}
if section is None or 'led' in section: if section is None or 'led' in section:
ret['led'] = { ret['led'] = {
'state_all': list(LED.COLOR.keys()), 'state_all': list(LED.COLOR.keys()),
@@ -1851,7 +1358,13 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
def _hardware_send_test_set(self, options: Dict[str, str]) -> bool: def _hardware_send_test_set(self, options: Dict[str, str]) -> bool:
# TODO write options files # TODO write options files
return False return False
@logging_info
def show_device_data(self, device: int):
client = self.data_server.client()
if client is not None:
with client:
client.show_data(device)
class _RandomCrashThread(ServerThread): class _RandomCrashThread(ServerThread):
def __init__(self): def __init__(self):
+119 -102
View File
@@ -41,7 +41,7 @@ class RecordingProcess(Process):
connect to DB and send sql command connect to DB and send sql command
""" """
def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, meta_path, def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, queue_msg, meta_path,
device_info, parameter, parent, recording_file_name, data_format, device_info, parameter, parent, recording_file_name, data_format,
mqtt_ip, mqtt_port, mqtt_ip, mqtt_port,
name = 'Recording-Process', database = None): name = 'Recording-Process', database = None):
@@ -82,6 +82,7 @@ class RecordingProcess(Process):
self._queue_rec = queue_rec self._queue_rec = queue_rec
self._queue_ds = queue_ds self._queue_ds = queue_ds
self._queue_msg = queue_msg
self.queue_flag = True self.queue_flag = True
self._is_close = True self._is_close = True
@@ -98,6 +99,14 @@ class RecordingProcess(Process):
self._last_cnt = [-1, -1, -1, -1, -1, -1, -1, -1] self._last_cnt = [-1, -1, -1, -1, -1, -1, -1, -1]
self._wrong_cnt = 0 self._wrong_cnt = 0
# elite data length
self._elite_data_len = 40
self._mem_header_len = 3
self._mem_tailer_len = 6
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
self._decoder = self.data_format()
self._start_time = time()
def ensure_data_format(self) -> DataDecodeFormat: def ensure_data_format(self) -> DataDecodeFormat:
if isinstance(self._data_format, (str, bytes)): if isinstance(self._data_format, (str, bytes)):
@@ -127,9 +136,9 @@ class RecordingProcess(Process):
decoder._prev_data = self._prev_data decoder._prev_data = self._prev_data
decoder._prev_delta_time = self._prev_delta_time decoder._prev_delta_time = self._prev_delta_time
decoder._prev_time_stamp = self._prev_time_stamp decoder._prev_time_stamp = self._prev_time_stamp
# elif isinstance(decoder, I4V4Z4T4DataDecoder): elif isinstance(decoder, I4V4Z4T4DataDecoder):
# get cycle_time from meta file # get cycle_time from meta file
# decoder._mode = self._meta_file.configuration.MODE decoder._mode = self._meta_file.configuration.get_parameter('MODE')
# decoder._cycle_start_time = self._cycle_start_time # decoder._cycle_start_time = self._cycle_start_time
elif isinstance(decoder, NeuliveThreeOneDataDecoder): elif isinstance(decoder, NeuliveThreeOneDataDecoder):
# get amp_gain from meta file # get amp_gain from meta file
@@ -145,11 +154,8 @@ class RecordingProcess(Process):
decoder._prev_time_stamp = self._prev_time_stamp decoder._prev_time_stamp = self._prev_time_stamp
elif isinstance(decoder, EISZeroOneDataDecoder): elif isinstance(decoder, EISZeroOneDataDecoder):
# get amp_gain from meta file # get amp_gain from meta file
decoder._ac_amp = self._meta_file.configuration.get_parameter('AC_AMP')
decoder._mode = self._meta_file.configuration.get_parameter('MODE') decoder._mode = self._meta_file.configuration.get_parameter('MODE')
decoder._freq_start = self._meta_file.configuration.get_parameter('FREQ_START') decoder._ac_amp = self._meta_file.configuration.get_parameter('EIS_AC_AMP')
decoder._freq_stop = self._meta_file.configuration.get_parameter('FREQ_STOP')
return decoder return decoder
@@ -160,11 +166,11 @@ class RecordingProcess(Process):
""" """
q = None q = None
try: try:
now = time() # now = time()
q = self._queue_rec.get() q = self._queue_rec.get()
get_queue_time_cost = time() - now # get_queue_time_cost = time() - now
if get_queue_time_cost > 1: # if get_queue_time_cost > 2:
print('get queue cost time', get_queue_time_cost) # print('get queue cost time', get_queue_time_cost)
except: except:
return False return False
finally: finally:
@@ -177,6 +183,8 @@ class RecordingProcess(Process):
self.final_write() self.final_write()
self.is_closed = True self.is_closed = True
return False return False
elif q == 'show_data':
self._decoder._show_data = not self._decoder._show_data
else: else:
self.rec_update() self.rec_update()
self.sync_data(q) self.sync_data(q)
@@ -190,18 +198,17 @@ class RecordingProcess(Process):
current_time = time() current_time = time()
if self._timer is not None: if self._timer is not None:
if current_time - self._timer > 1.5: if current_time - self._timer > 1.5:
print('time, sync_data routine_time', current_time, current_time - self._timer) print('time, sync_data routine_time', 'device:', self._device, datetime.now(), current_time, current_time - self._timer)
self._isTimeOut = True self._isTimeOut = True
self._timer = current_time self._timer = current_time
decoder = self.data_format()
# print('sync_data') # print('sync_data')
# print('data',data) # print('data',data)
# print('server/data', self._prev_delta_time,self._prev_time_stamp, self._prev_data) # print('server/data', self._prev_delta_time,self._prev_time_stamp, self._prev_data)
if data is None or len(data) == 0: if data is None or len(data) == 0:
result = decoder.decode(b'') result = self._decoder.decode(b'')
if result is not None: if result is not None:
ret = result ret = result
@@ -215,25 +222,13 @@ class RecordingProcess(Process):
for offset, section in self._foreach_data_section(data): for offset, section in self._foreach_data_section(data):
# for section in self._neu_foreach_data_section(data): # for section in self._neu_foreach_data_section(data):
result = decoder.decode(section) result = self._decoder.decode(section)
# if self._isTimeOut: # if self._isTimeOut:
# try: # try:
# print('result: ', result.data_size) # print('result: ', result.data_size)
# except: # except:
# pass # pass
try:
if isinstance(decoder, I4V4Z4T4DataDecoder) or isinstance(decoder, EISZeroOneDataDecoder):
if decoder.isFinishMode is not None and decoder.isFinishMode() == 1:
content = {}
content['header'] = 'device_instruction/0'
content['device'] = result.device
content['instruction'] = 'interrupt'
self._mqtt_thread.publish('device_instruction',json_stringify(content), True)
# self.server.stop_sync(self.device)
except RuntimeError as e:
print(e)
if result is not None: if result is not None:
## ##
if len(self._mqtt_send_data_ch_level) == 0: if len(self._mqtt_send_data_ch_level) == 0:
@@ -250,9 +245,27 @@ class RecordingProcess(Process):
self._writer.channels_update(ret[0].channels()) self._writer.channels_update(ret[0].channels())
self._writer.write(ret, self._mqtt_send_data_ch_level) self._writer.write(ret, self._mqtt_send_data_ch_level)
# print('write time: ', time() - ctime1) # print('write time: ', time() - ctime1)
# print(ret) # print(ret)
try:
time_duration = self._meta_file.configuration.get_parameter('TIME_DURATION')
if time_duration and time_duration is not 0 and time() - self._start_time >= time_duration:
self._queue_msg.put(['ds', self._device, 'interrupt'])
return None
if isinstance(self._decoder, I4V4Z4T4DataDecoder) or isinstance(self._decoder, EISZeroOneDataDecoder):
if self._decoder.isFinishMode is not None and self._decoder.isFinishMode() == 1:
self._queue_msg.put(['ds', self._device, 'interrupt'])
return None
# content = {}
# content['header'] = 'device_instruction/0'
# content['device'] = result.device
# content['instruction'] = 'interrupt'
# self._mqtt_thread.publish('device_instruction',json_stringify(content), True)
# self.server.stop_sync(self.device)
except RuntimeError as e:
print(e)
del ret del ret
del data del data
return return
@@ -290,7 +303,8 @@ class RecordingProcess(Process):
self._last_cnt[7] = head_counter - 1 self._last_cnt[7] = head_counter - 1
last_data_cnt = self._last_cnt[7] last_data_cnt = self._last_cnt[7]
if (head != 255 or device_id != device): # dont save to section when head or id is wrong
if (head != 255 or device_id != device or head_counter > 255 or head_counter < 0):
save = False save = False
last_data_cnt = last_data_cnt + 1 last_data_cnt = last_data_cnt + 1
@@ -332,60 +346,58 @@ class RecordingProcess(Process):
return save return save
def _check_jump_ram(self, raw_data: bytes, colum_now: int, colum_total: int, save: bool, device: int): def _check_jump_ram(self, raw_data: bytes, colum_now: int, colum_total: int, save: bool, device: int, data_len: int):
i = colum_now col = colum_now
save = False
if (raw_data[i][0] == 255 and raw_data[i][3] == device): if raw_data[col][0] != 255 or raw_data[col][3] != device:
if colum_total < 3: return save
print('this ram data < 3 records, need to fix, colum_total = ', colum_total)
if colum_total == 1:
print('raw_data[0]', raw_data[0])
elif colum_total == 2: if colum_total == 1:
print('raw_data[0]', raw_data[0]) print('this ram data < 3 records, colum_total = ', colum_total)
print('raw_data[1]', raw_data[1]) print('raw_data[0]', list(raw_data[0]))
save = True
# return save
else: elif colum_total == 2:
print('this ram data < 3 records, colum_total = ', colum_total)
print('raw_data[0]', list(raw_data[0]))
print('raw_data[1]', list(raw_data[1]))
if (raw_data[col + 1][1] - raw_data[col][1] == 1) or (raw_data[col][1] == 255 and raw_data[col + 1][1] == 0):
save = True
if((raw_data[i + 1][1] - raw_data[i][1] == 1 and raw_data[i + 2][1] - raw_data[i + 1][1] == 1) or elif colum_total >= 3:
(raw_data[i][1] == 255 and raw_data[i + 1][1] == 0 and raw_data[i + 2][1] == 1) or if (raw_data[col + 1][1] - raw_data[col][1] == 1 and raw_data[col + 2][1] - raw_data[col + 1][1] == 1) or\
(raw_data[i][1] == 254 and raw_data[i + 1][1] == 255 and raw_data[i + 2][1] == 0)): (raw_data[col][1] == 255 and raw_data[col + 1][1] == 0 and raw_data[col + 2][1] == 1) or\
(raw_data[col][1] == 254 and raw_data[col + 1][1] == 255 and raw_data[col + 2][1] == 0):
save = True
if ((raw_data[i][1] == 255 and raw_data[i + 1][1] == 0 and raw_data[i + 2][1] == 1) or if save == True:
(raw_data[i][1] == 254 and raw_data[i + 1][1] == 255 and raw_data[i + 2][1] == 0)): self._skip_ram_cnt += 1
print('cnt = [254, 255, 0] or [255, 0, 1]') last_data_cnt = raw_data[col][1]
if (device == 4):
print('self._last_cnt[4]:', self._last_cnt[4], ', last_data_cnt:', last_data_cnt)
if (device == 5):
print('self._last_cnt[5]:', self._last_cnt[5], ', last_data_cnt:', last_data_cnt)
if (device == 6):
print('self._last_cnt[6]:', self._last_cnt[6], ', last_data_cnt:', last_data_cnt)
if (device == 7):
print('self._last_cnt[7]:', self._last_cnt[7], ', last_data_cnt:', last_data_cnt)
print('skip RAM, but data is right, solve data', list(raw_data[col][0:3]),'|', list(raw_data[colum_total-1][0:3]), 'skip Ram', self._skip_ram_cnt, 'times \n')
save = True if (device == 4):
self._skip_ram_cnt += 1 self._last_cnt[4] = last_data_cnt
last_data_cnt = raw_data[i][1]
if (device == 4):
print('self._last_cnt[4]:', self._last_cnt[4], ', last_data_cnt:', last_data_cnt)
if (device == 5):
print('self._last_cnt[5]:', self._last_cnt[5], ', last_data_cnt:', last_data_cnt)
if (device == 6):
print('self._last_cnt[6]:', self._last_cnt[6], ', last_data_cnt:', last_data_cnt)
if (device == 7):
print('self._last_cnt[7]:', self._last_cnt[7], ', last_data_cnt:', last_data_cnt)
print('skip RAM, but data is right, solve data', list(raw_data[i][0:3]),'|', list(raw_data[colum_total-1][0:3]), 'skip Ram', self._skip_ram_cnt, 'times \n')
# print('data:')
# print('|', list(raw_data[0]))
# print('|', list(raw_data[1]))
# print('| ... ... ...')
# print('| ... ... ...')
# print('|', list(raw_data[colum_total-1]))
if (device == 4): elif (device == 5):
self._last_cnt[4] = last_data_cnt self._last_cnt[5] = last_data_cnt
elif (device == 5): elif (device == 6):
self._last_cnt[5] = last_data_cnt self._last_cnt[6] = last_data_cnt
elif (device == 6): elif (device == 7):
self._last_cnt[6] = last_data_cnt self._last_cnt[7] = last_data_cnt
elif (device == 7):
self._last_cnt[7] = last_data_cnt
return save return save
def _neu_foreach_data_section(self, data: bytes): def _neu_foreach_data_section(self, data: bytes):
@@ -500,54 +512,59 @@ class RecordingProcess(Process):
:return: :return:
""" """
raw_data = [] raw_data = []
index = 0 records = 0
elite_data_len = 40
mem_header_len = 3
mem_tailer_len = 8
single_data_len = elite_data_len + mem_header_len + mem_tailer_len
device = self._device
print_flag = False print_flag = False
device = self._device
single_data_len = self._single_data_len
mem_header_len = self._mem_header_len
# packet section data use two microarray # packet section data use two microarray
for i in range(0, len(data), single_data_len): for i in range(0, len(data), single_data_len):
index = index + 1 records = records + 1
for j in range(index, index + 1): raw_data.append(data[i : i + single_data_len])
raw_data.append(data[i : i + single_data_len]) if len(data[i : i + 10]) < 10:
print('data dont be package:', raw_data[records - 1], 'index:', records - 1)
del raw_data[records - 1]
records = records - 1
# check cnt # check cnt
for i in range(index): for i in range(records):
# if jump cnt, don't save data # if jump cnt, don't save data
save = self._check_cnt(raw_data[i], device) save = self._check_cnt(raw_data[i], device)
# # if jump Ram, also can handle data # # if jump Ram, also can handle data
if save == False: if save == False:
save = self._check_jump_ram(raw_data, i, index, save, device) save = self._check_jump_ram(raw_data, i, records, save, device, single_data_len)
if (save == True): if (save == True):
section = raw_data[i] section = raw_data[i]
if (section[0 : mem_header_len] == section[single_data_len - 3: single_data_len]): check_sum = sum(section[0 : single_data_len - 1]) & 0b11111111
section = section + b'\x00'
if (check_sum != section[single_data_len - 1]):
else: print('check number not match,',
section = section + b'\x01' list(section[0 : mem_header_len]), section[-1], '!=', check_sum, 'device:', device, ',', datetime.now())
print('header != tailer,',
list(section[0 : mem_header_len]),
list(section[single_data_len - 3: single_data_len]),
'device:', device, ',', datetime.now())
if (i-1 >= 0): if (i-1 >= 0):
print('header != tailer', list(raw_data[i-1]), 'raw:', i-1) print('check number not match', list(raw_data[i-1]), 'raw:', i-1)
print('header != tailer', list(section), 'raw:', i)
if (i+1 <= index): print('check number not match', list(raw_data[i]), 'raw:', i)
print('header != tailer', list(raw_data[i+1]), 'raw:', i+1, '\n')
if (i+1 <= records):
section = section[3:] print('check number not match', list(raw_data[i+1]), 'raw:', i+1, '\n')
section = section + b'\x01'
print('delete data:', list(raw_data[i][0:3]), 'raw:', i, '\n')
continue
else:
section = section + b'\x00'
# section = section[3:]
yield None, section yield None, section
else: else:
print_flag = True print_flag = True
print('delete data:', list(raw_data[i][0:3]), 'raw:', i+1, '\n') print('delete data:', list(raw_data[i][0:3]), 'raw:', i, '\n')
# if print_flag: # if print_flag:
# print('delete data context:') # print('delete data context:')
@@ -589,7 +606,7 @@ class RecordingProcess(Process):
def final_write(self): def final_write(self):
if self._writer is not None: if self._writer is not None:
return self._writer.close() return self._writer.close(self._mqtt_send_data_ch_level)
else: else:
return False return False
+7 -5
View File
@@ -93,13 +93,15 @@ class SocketClient(metaclass=abc.ABCMeta):
if self._socket is None: if self._socket is None:
try: try:
self._socket = Socket(AF_UNIX, SOCK_STREAM) self._socket = Socket(AF_UNIX, SOCK_STREAM)
self._socket.settimeout(1) self._socket.settimeout(5)
self._socket.connect(self._socket_file) self._socket.connect(self._socket_file)
except FileNotFoundError as e: except Exception as e:
raise RuntimeError('server not available') from e print('open_socket error:', e)
# except FileNotFoundError as e:
# raise RuntimeError('server not available') from e
except ConnectionRefusedError as e: # except ConnectionRefusedError as e:
raise RuntimeError('server crash') from e # raise RuntimeError('server crash') from e
def close_socket(self): def close_socket(self):
if self._socket is not None: if self._socket is not None:
@@ -1,14 +1,15 @@
{ {
"name": "EliteZM15", "name": "Elite_BAT_1.0",
"version": "1.2.30", "version": "1.2.30",
"match_rule": { "match_rule": {
"local_name_pattern": "Elite.*", "local_name_pattern": "Elite.*",
"major_product_number": 0, "major_product_number": 0,
"minor_product_number": 2, "minor_product_number": 3,
"major_version_number": 1, "major_version_number": 1,
"minor_version_number": 6 "minor_version_number": 0
}, },
"constant": { "constant": {
"TIME_MAX": 100000,
"VOLT_MAX": 65536, "VOLT_MAX": 65536,
"Const_Current_Range": 1500001, "Const_Current_Range": 1500001,
"BLE_WRITE_MAX": 255 "BLE_WRITE_MAX": 255
@@ -17,7 +18,7 @@
"DPV_e_init": { "DPV_e_init": {
"description": "DPV initial voltage ", "description": "DPV initial voltage ",
"record_meta": true, "record_meta": true,
"initial":20000, "initial": 20000,
"domain": [ "domain": [
50001 50001
], ],
@@ -28,7 +29,7 @@
"DPV_e_final": { "DPV_e_final": {
"description": "DPV final voltage", "description": "DPV final voltage",
"record_meta": true, "record_meta": true,
"initial":30000, "initial": 30000,
"domain": [ "domain": [
50001 50001
], ],
@@ -39,7 +40,7 @@
"DPV_e_1": { "DPV_e_1": {
"description": "DPV voltage return 1", "description": "DPV voltage return 1",
"record_meta": true, "record_meta": true,
"initial":35000, "initial": 35000,
"domain": [ "domain": [
50001 50001
], ],
@@ -50,7 +51,7 @@
"DPV_e_2": { "DPV_e_2": {
"description": "DPV voltage return 2", "description": "DPV voltage return 2",
"record_meta": true, "record_meta": true,
"initial":15000, "initial": 15000,
"domain": [ "domain": [
50001 50001
], ],
@@ -61,7 +62,7 @@
"DPV_amp": { "DPV_amp": {
"description": "DPV pulse amplitude", "description": "DPV pulse amplitude",
"record_meta": true, "record_meta": true,
"initial":25125, "initial": 25125,
"domain": [ "domain": [
50001 50001
], ],
@@ -72,7 +73,7 @@
"DPV_pul_width": { "DPV_pul_width": {
"description": "DPV pulse width", "description": "DPV pulse width",
"record_meta": true, "record_meta": true,
"initial":50, "initial": 50,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -83,7 +84,7 @@
"DPV_increment": { "DPV_increment": {
"description": "DPV increment", "description": "DPV increment",
"record_meta": true, "record_meta": true,
"initial":25025, "initial": 25025,
"domain": [ "domain": [
50001 50001
], ],
@@ -94,7 +95,7 @@
"DPV_step_time": { "DPV_step_time": {
"description": "DPV step time = time of one period", "description": "DPV step time = time of one period",
"record_meta": true, "record_meta": true,
"initial":500, "initial": 500,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -105,7 +106,7 @@
"DPV_notify_rate": { "DPV_notify_rate": {
"description": "DPV sample rate", "description": "DPV sample rate",
"record_meta": true, "record_meta": true,
"initial":1000, "initial": 1000,
"domain": [ "domain": [
1001 1001
], ],
@@ -113,10 +114,24 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"DPV_curr_rec": {
"description": "DPV current recording period start",
"record_meta": true,
"initial": [
25,
100
],
"domain": {
"list": [
101
]
},
"value": "VALUE"
},
"DPV_curr_rec_min": { "DPV_curr_rec_min": {
"description": "DPV current recording period start", "description": "DPV current recording period start",
"record_meta": true, "record_meta": true,
"initial":25, "initial": 25,
"domain": [ "domain": [
101 101
], ],
@@ -127,7 +142,7 @@
"DPV_curr_rec_max": { "DPV_curr_rec_max": {
"description": "DPV current recording period end", "description": "DPV current recording period end",
"record_meta": true, "record_meta": true,
"initial":100, "initial": 100,
"domain": [ "domain": [
101 101
], ],
@@ -138,11 +153,8 @@
"DPV_pulse_option": { "DPV_pulse_option": {
"description": "Invert of pulse option", "description": "Invert of pulse option",
"record_meta": true, "record_meta": true,
"initial": 0, "domain": "bool",
"value": [ "initial": false
0,
1
]
}, },
"DPV_mode": { "DPV_mode": {
"description": "AUTO: 0 / ADVANCED: 1/ ENGINEERING: 2", "description": "AUTO: 0 / ADVANCED: 1/ ENGINEERING: 2",
@@ -157,16 +169,29 @@
"DPV_engineering_enable": { "DPV_engineering_enable": {
"description": "Engineering mode switch", "description": "Engineering mode switch",
"record_meta": true, "record_meta": true,
"initial": 0, "domain": "bool",
"value": [ "initial": false
0, },
1 "V_initial": {
] "description": "Pulse Mode Segment Voltage",
"record_meta": true,
"initial": [
50000,
25000,
25000,
25000
],
"domain": {
"list": [
50001
]
},
"value": "VALUE"
}, },
"V_initial_0": { "V_initial_0": {
"description": "Pulse Mode Segment Voltage 0", "description": "Pulse Mode Segment Voltage 0",
"record_meta": true, "record_meta": true,
"initial":50000, "initial": 50000,
"domain": [ "domain": [
50001 50001
], ],
@@ -177,7 +202,7 @@
"V_initial_1": { "V_initial_1": {
"description": "Pulse Mode Segment Voltage 1", "description": "Pulse Mode Segment Voltage 1",
"record_meta": true, "record_meta": true,
"initial":25000, "initial": 25000,
"domain": [ "domain": [
50001 50001
], ],
@@ -188,7 +213,7 @@
"V_initial_2": { "V_initial_2": {
"description": "Pulse Mode Segment Voltage 2", "description": "Pulse Mode Segment Voltage 2",
"record_meta": true, "record_meta": true,
"initial":25000, "initial": 25000,
"domain": [ "domain": [
50001 50001
], ],
@@ -199,7 +224,7 @@
"V_initial_3": { "V_initial_3": {
"description": "Pulse Mode Segment Voltage 3", "description": "Pulse Mode Segment Voltage 3",
"record_meta": true, "record_meta": true,
"initial":25000, "initial": 25000,
"domain": [ "domain": [
50001 50001
], ],
@@ -207,10 +232,26 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"t_pulse": {
"description": "Pulse Mode Segment Duration",
"record_meta": true,
"initial": [
750,
9250,
1000,
1000
],
"domain": {
"list": [
1000001
]
},
"value": "VALUE"
},
"t_pulse_0": { "t_pulse_0": {
"description": "Pulse Mode Segment Duration 0", "description": "Pulse Mode Segment Duration 0",
"record_meta": true, "record_meta": true,
"initial":750, "initial": 750,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -221,7 +262,7 @@
"t_pulse_1": { "t_pulse_1": {
"description": "Pulse Mode Segment Duration 1", "description": "Pulse Mode Segment Duration 1",
"record_meta": true, "record_meta": true,
"initial":9250, "initial": 9250,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -232,7 +273,7 @@
"t_pulse_2": { "t_pulse_2": {
"description": "Pulse Mode Segment Duration 2", "description": "Pulse Mode Segment Duration 2",
"record_meta": true, "record_meta": true,
"initial":1000, "initial": 1000,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -243,7 +284,7 @@
"t_pulse_3": { "t_pulse_3": {
"description": "Pulse Mode Segment Duration 3", "description": "Pulse Mode Segment Duration 3",
"record_meta": true, "record_meta": true,
"initial":1000, "initial": 1000,
"domain": [ "domain": [
1000001 1000001
], ],
@@ -251,10 +292,40 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"CURR_REC": {
"description": "Pulse Mode Current Recording Period",
"record_meta": true,
"initial": [
[
35,
90
],
[
35,
99
],
[
35,
95
],
[
35,
95
]
],
"domain": {
"list": {
"list": [
100
]
}
},
"value": "VALUE"
},
"CURR_REC_START_0": { "CURR_REC_START_0": {
"description": "Pulse Mode Current Recording Period Start", "description": "Pulse Mode Current Recording Period Start",
"record_meta": true, "record_meta": true,
"initial":35, "initial": 35,
"domain": [ "domain": [
100 100
], ],
@@ -265,7 +336,7 @@
"CURR_REC_START_1": { "CURR_REC_START_1": {
"description": "Pulse Mode Current Recording Period Start", "description": "Pulse Mode Current Recording Period Start",
"record_meta": true, "record_meta": true,
"initial":35, "initial": 35,
"domain": [ "domain": [
100 100
], ],
@@ -276,7 +347,7 @@
"CURR_REC_START_2": { "CURR_REC_START_2": {
"description": "Pulse Mode Current Recording Period Start", "description": "Pulse Mode Current Recording Period Start",
"record_meta": true, "record_meta": true,
"initial":35, "initial": 35,
"domain": [ "domain": [
100 100
], ],
@@ -287,7 +358,7 @@
"CURR_REC_START_3": { "CURR_REC_START_3": {
"description": "Pulse Mode Current Recording Period Start", "description": "Pulse Mode Current Recording Period Start",
"record_meta": true, "record_meta": true,
"initial":35, "initial": 35,
"domain": [ "domain": [
100 100
], ],
@@ -298,7 +369,7 @@
"CURR_REC_END_0": { "CURR_REC_END_0": {
"description": "Pulse Mode Current Recording Period End", "description": "Pulse Mode Current Recording Period End",
"record_meta": true, "record_meta": true,
"initial":90, "initial": 90,
"domain": [ "domain": [
100 100
], ],
@@ -309,7 +380,7 @@
"CURR_REC_END_1": { "CURR_REC_END_1": {
"description": "Pulse Mode Current Recording Period End", "description": "Pulse Mode Current Recording Period End",
"record_meta": true, "record_meta": true,
"initial":99, "initial": 99,
"domain": [ "domain": [
100 100
], ],
@@ -320,7 +391,7 @@
"CURR_REC_END_2": { "CURR_REC_END_2": {
"description": "Pulse Mode Current Recording Period End", "description": "Pulse Mode Current Recording Period End",
"record_meta": true, "record_meta": true,
"initial":95, "initial": 95,
"domain": [ "domain": [
100 100
], ],
@@ -331,7 +402,7 @@
"CURR_REC_END_3": { "CURR_REC_END_3": {
"description": "Pulse Mode Current Recording Period End", "description": "Pulse Mode Current Recording Period End",
"record_meta": true, "record_meta": true,
"initial":95, "initial": 95,
"domain": [ "domain": [
100 100
], ],
@@ -339,6 +410,40 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"segment_ui_order": {
"description": "Pulse Mode Segment Order",
"record_meta": true,
"initial": [
0,
1,
-1,
-1
],
"domain": {
"list": [
-1,
6
]
},
"value": "VALUE"
},
"segment_order": {
"description": "Pulse Mode Segment Order",
"record_meta": true,
"initial": [
0,
1,
-1,
-1
],
"domain": {
"list": [
-1,
6
]
},
"value": "VALUE"
},
"segment_ui_order_0": { "segment_ui_order_0": {
"description": "Pulse Mode Segment UI Order 0, value: segment ID + 1", "description": "Pulse Mode Segment UI Order 0, value: segment ID + 1",
"record_meta": true, "record_meta": true,
@@ -478,13 +583,14 @@
"Constant Current", "Constant Current",
"Cyclic Voltammetry", "Cyclic Voltammetry",
"Linear Sweep Voltammetry", "Linear Sweep Voltammetry",
"Chronoamperometric Graph", "Chronoamperometric",
"Cali DAC - test", "Cali DAC - test",
"Cali ADC - test", "Cali ADC - test",
"Dev Mode", "Dev Mode",
"Open Circuit Potential", "Open Circuit Potential",
"Pulse Sensing", "Pulse Sensing",
"Differential Pulse Voltammetry (DPV)" "Differential Pulse Voltammetry (DPV)",
"Chronopotentiometry"
] ]
}, },
"VOLT_ORIGIN": { "VOLT_ORIGIN": {
@@ -644,7 +750,7 @@
}, },
"CURRNET_LIMIT_VALUE": { "CURRNET_LIMIT_VALUE": {
"description": "Current value Setting", "description": "Current value Setting",
"initial":1500000, "initial": 1500000,
"domain": [ "domain": [
"Const_Current_Range" "Const_Current_Range"
], ],
@@ -685,6 +791,15 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"CC_CP_SPEED": {
"description": "charge speed for CC and CP mode",
"initial": 1,
"value": [
"low",
"normal",
"high"
]
},
"ADC_LEVEL_I_15": { "ADC_LEVEL_I_15": {
"description": "ADC level", "description": "ADC level",
"record_meta": true, "record_meta": true,
@@ -762,6 +877,17 @@
"s", "s",
"ms" "ms"
] ]
},
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
} }
}, },
"instruction": { "instruction": {
@@ -812,7 +938,8 @@
"7": "set_adc_gain_I", "7": "set_adc_gain_I",
"8": "set_adc_gain_I", "8": "set_adc_gain_I",
"9": "set_adc_gain_I", "9": "set_adc_gain_I",
"13": "set_adc_gain_I" "13": "set_adc_gain_I",
"16": "set_adc_gain_I"
} }
}, },
{ {
@@ -827,7 +954,8 @@
"7": "set_adc_gain_Vin", "7": "set_adc_gain_Vin",
"8": "set_adc_gain_Vin", "8": "set_adc_gain_Vin",
"9": "set_adc_gain_Vin", "9": "set_adc_gain_Vin",
"13": "set_adc_gain_Vin" "13": "set_adc_gain_Vin",
"16": "set_adc_gain_Vin"
} }
}, },
{ {
@@ -845,7 +973,8 @@
"9": "curve_const_vscan", "9": "curve_const_vscan",
"13": "curve_ocp", "13": "curve_ocp",
"14": "curve_pulse_sensing", "14": "curve_pulse_sensing",
"15": "curve_dpv" "15": "curve_dpv",
"16": "curve_cp"
} }
}, },
{ {
@@ -1043,6 +1172,7 @@
"vb": "Const_Current_value", "vb": "Const_Current_value",
"vc": "VOLTSTOP_MAX", "vc": "VOLTSTOP_MAX",
"vd": "VOLTSTOP_MIN", "vd": "VOLTSTOP_MIN",
"ve": "CC_CP_SPEED",
"pa": "ADC_LEVEL_I_15", "pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15", "pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15", "pc": "DAC_LEVEL_V_OUT_15",
@@ -1054,7 +1184,31 @@
"B>va;4B>vb;2B>vc;2B>vd;", "B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;", "4b>pa;4b>pb;",
"4b>pc;4b>pd;", "4b>pc;4b>pd;",
"2B>pe" "2B>pe;",
"4b>0b0001;4b>ve"
]
},
"curve_cp": {
"type": "RIS",
"parameter": {
"va": "Charge",
"vb": "Const_Current_value",
"vc": "VOLTSTOP_MAX",
"vd": "VOLTSTOP_MIN",
"ve": "CC_CP_SPEED",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"X0C;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
"2B>pe;",
"4b>0b0000;4b>ve"
] ]
}, },
"curve_cv3": { "curve_cv3": {
@@ -1180,58 +1334,67 @@
}, },
"curve_pulse_sensing": [ "curve_pulse_sensing": [
{ {
"expression": "segment_ui_order_0", "expression": "segment_ui_order[0]",
"when": { "when": {
"1": "pul_sen_segment_0", "0": "pul_sen_segment_0",
"2": "pul_sen_segment_1", "1": "pul_sen_segment_1",
"3": "pul_sen_segment_2", "2": "pul_sen_segment_2",
"4": "pul_sen_segment_3" "3": "pul_sen_segment_3"
} }
}, },
{ {
"expression": "segment_ui_order_1", "expression": "segment_ui_order[1]",
"when": { "when": {
"1": "pul_sen_segment_0", "0": "pul_sen_segment_0",
"2": "pul_sen_segment_1", "1": "pul_sen_segment_1",
"3": "pul_sen_segment_2", "2": "pul_sen_segment_2",
"4": "pul_sen_segment_3" "3": "pul_sen_segment_3"
} }
}, },
{ {
"expression": "segment_ui_order_2", "expression": "segment_ui_order[2]",
"when": { "when": {
"1": "pul_sen_segment_0", "0": "pul_sen_segment_0",
"2": "pul_sen_segment_1", "1": "pul_sen_segment_1",
"3": "pul_sen_segment_2", "2": "pul_sen_segment_2",
"4": "pul_sen_segment_3" "3": "pul_sen_segment_3"
} }
}, },
{ {
"expression": "segment_ui_order_3", "expression": "segment_ui_order[3]",
"when": { "when": {
"1": "pul_sen_segment_0", "0": "pul_sen_segment_0",
"2": "pul_sen_segment_1", "1": "pul_sen_segment_1",
"3": "pul_sen_segment_2", "2": "pul_sen_segment_2",
"4": "pul_sen_segment_3" "3": "pul_sen_segment_3"
} }
}, },
"pul_sen_start" "pul_sen_start"
], ],
"pul_sen_start": { "pul_sen_start": {
"type": "RIS", "type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [ "data": [
"1X0D;", "1X0D;",
"1XFF" "1XFF",
"4b>pa;4b>pb;",
"4b>pc;4b>pd"
] ]
}, },
"pul_sen_segment_0": { "pul_sen_segment_0": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"va": "V_initial_0", "va": "V_initial[0]",
"vb": "t_pulse_0", "vb": "t_pulse[0]",
"vc": "CURR_REC_START_0", "vc": "CURR_REC[0][0]",
"vd": "CURR_REC_END_0", "vd": "CURR_REC[0][1]",
"ve": "segment_order_0 - 1", "ve": "segment_order.index(segment_order[0])",
"pa": "ADC_LEVEL_I_15", "pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15", "pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15", "pc": "DAC_LEVEL_V_OUT_15",
@@ -1247,11 +1410,11 @@
"pul_sen_segment_1": { "pul_sen_segment_1": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"va": "V_initial_1", "va": "V_initial[1]",
"vb": "t_pulse_1", "vb": "t_pulse[1]",
"vc": "CURR_REC_START_1", "vc": "CURR_REC[1][0]",
"vd": "CURR_REC_END_1", "vd": "CURR_REC[1][1]",
"ve": "segment_order_1 - 1", "ve": "segment_order.index(segment_order[1])",
"pa": "ADC_LEVEL_I_15", "pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15", "pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15", "pc": "DAC_LEVEL_V_OUT_15",
@@ -1267,11 +1430,11 @@
"pul_sen_segment_2": { "pul_sen_segment_2": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"va": "V_initial_2", "va": "V_initial[2]",
"vb": "t_pulse_2", "vb": "t_pulse[2]",
"vc": "CURR_REC_START_2", "vc": "CURR_REC[2][0]",
"vd": "CURR_REC_END_2", "vd": "CURR_REC[2][1]",
"ve": "segment_order_2 - 1", "ve": "segment_order.index(segment_order[2])",
"pa": "ADC_LEVEL_I_15", "pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15", "pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15", "pc": "DAC_LEVEL_V_OUT_15",
@@ -1287,11 +1450,11 @@
"pul_sen_segment_3": { "pul_sen_segment_3": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"va": "V_initial_3", "va": "V_initial[3]",
"vb": "t_pulse_3", "vb": "t_pulse[3]",
"vc": "CURR_REC_START_3", "vc": "CURR_REC[3][0]",
"vd": "CURR_REC_END_3", "vd": "CURR_REC[3][1]",
"ve": "segment_order_3 - 1", "ve": "segment_order.index(segment_order[3])",
"pa": "ADC_LEVEL_I_15", "pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15", "pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15", "pc": "DAC_LEVEL_V_OUT_15",
@@ -1304,9 +1467,7 @@
"2B>va;4B>vb;1B>vc;1B>vd;1B>ve" "2B>va;4B>vb;1B>vc;1B>vd;1B>ve"
] ]
}, },
"curve_dpv": [
"curve_dpv":[
{ {
"expression": "DPV_mode", "expression": "DPV_mode",
"when": { "when": {
@@ -1354,8 +1515,8 @@
"parameter": { "parameter": {
"va": "DPV_step_time", "va": "DPV_step_time",
"vb": "DPV_notify_rate", "vb": "DPV_notify_rate",
"vc": "DPV_curr_rec_min", "vc": "DPV_curr_rec[0]",
"vd": "DPV_curr_rec_max" "vd": "DPV_curr_rec[1]"
}, },
"data": [ "data": [
"1X0E;", "1X0E;",
@@ -1365,14 +1526,20 @@
}, },
"dpv_auto_mode_ins_final": { "dpv_auto_mode_ins_final": {
"type": "RIS", "type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [ "data": [
"1X0E;", "1X0E;",
"1XFF" "1XFF;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd"
] ]
}, },
"dpv_advanced_mode": [ "dpv_advanced_mode": [
"dpv_advanced_mode_ins_1", "dpv_advanced_mode_ins_1",
"dpv_advanced_mode_ins_2", "dpv_advanced_mode_ins_2",
@@ -1412,8 +1579,8 @@
"parameter": { "parameter": {
"va": "DPV_step_time", "va": "DPV_step_time",
"vb": "DPV_notify_rate", "vb": "DPV_notify_rate",
"vc": "DPV_curr_rec_min", "vc": "DPV_curr_rec[0]",
"vd": "DPV_curr_rec_max" "vd": "DPV_curr_rec[1]"
}, },
"data": [ "data": [
"1X10;", "1X10;",
@@ -1437,9 +1604,18 @@
}, },
"dpv_advanced_mode_ins_final": { "dpv_advanced_mode_ins_final": {
"type": "RIS", "type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [ "data": [
"1X10;", "1X10;",
"1XFF" "1XFF;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd"
] ]
}, },
"dpv_engineering_mode": [ "dpv_engineering_mode": [
@@ -1457,18 +1633,6 @@
"dpv_engineering_mode_advanced": [ "dpv_engineering_mode_advanced": [
"dpv_advanced_mode" "dpv_advanced_mode"
], ],
"VIS_CC_ZERO": [
"_data_format('I4V4Z4T4')",
"_disable_cache(False)",
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"VIS_CC_ZERO",
"_sync(True)",
"VIS_STI"
],
"ble_instru_send": [ "ble_instru_send": [
"ble_write", "ble_write",
"_cdr('20X>ADC_VALUE_I')" "_cdr('20X>ADC_VALUE_I')"
@@ -1499,6 +1663,4 @@
] ]
} }
} }
} }
@@ -1,5 +1,5 @@
{ {
"name": "EliteZM02", "name": "Elite_EDC_1.4",
"version": "1.2.30", "version": "1.2.30",
"match_rule": { "match_rule": {
"local_name_pattern": "Elite.*", "local_name_pattern": "Elite.*",
@@ -492,14 +492,6 @@
"1XC0;1X02;4B>ve;2B>vf;4B>vg;B>cn" "1XC0;1X02;4B>ve;2B>vf;4B>vg;B>cn"
] ]
}, },
"VIS_CC_ZERO": [
"_data_format('I4V4Z4T4')",
"_disable_cache(False)",
"_notify(True)",
"VIS_CC_ZERO",
"_sync(True)",
"VIS_STI"
],
"curve_cv3_high_cycle": { "curve_cv3_high_cycle": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
{ {
"name": "EliteEIS", "name": "Elite_EIS_1.0",
"version": "1.2.30", "version": "1.2.30",
"match_rule": { "match_rule": {
"local_name_pattern": "Elite.*", "local_name_pattern": "Elite.*",
@@ -9,23 +9,29 @@
"minor_version_number": 0 "minor_version_number": 0
}, },
"constant": { "constant": {
"FREQ_MAX": 4294967296, "FREQ_MAX": 13333334,
"VOLT_MAX": 65536, "VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255 "BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
}, },
"parameters": { "parameters": {
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"CHANNEL": { "CHANNEL": {
"derzteription": "record channels", "derzteription": "record channels",
"record_meta": true, "record_meta": true,
"domain": "property", "domain": "property",
"value": "[0, 1, 2]" "value": "[0, 1, 2]"
}, },
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": { "SAMPLE_RATE": {
"description": "data sampling rate", "description": "data sampling rate",
"record_meta": true, "record_meta": true,
@@ -48,34 +54,78 @@
"description": "working mode", "description": "working mode",
"record_meta": true, "record_meta": true,
"value": [ "value": [
"EIS CURVE", "EIS CURVE",
"Cyclic Voltammetry", "Cyclic Voltammetry",
"Dev Mode" "Chronoamperometric",
"V-T Graph",
"R-T Graph",
"Dev Mode"
] ]
}, },
"FREQ_START": { "GENERAL_HS_RTIA": {
"description": "Start of Freq Scan", "description": "High speed rtia gain",
"record_meta": true, "record_meta": true,
"initial": 13422819, "initial": 4,
"value": [
0,
1,
2,
3,
4
],
"on_change": "set_general_hs_rtia"
},
"EIS_DC_BIAS": {
"description": "DC voltage bias",
"record_meta": true,
"initial": 25000,
"domain": [ "domain": [
"FREQ_MAX" "VOLT_MAX"
], ],
"value": { "value": {
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"FREQ_STOP": { "EIS_AC_AMP": {
"description": "End of Freq Scan", "description": "AC Amplitude",
"record_meta": true, "record_meta": true,
"initial": 7, "initial": 25,
"domain": [ "domain": [
"FREQ_MAX" 2048
], ]
"value": {
"expression": "VALUE"
}
}, },
"DELAY": { "EIS_FREQ": {
"description": "[start, stop] of frequency scan",
"record_meta": true,
"initial": [
13333333,
7
],
"domain": {
"list": [
"FREQ_MAX"
]
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 10,
"domain": [
11
]
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
},
"EIS_DELAY": {
"description": "Wait x peroid before start taking measurements", "description": "Wait x peroid before start taking measurements",
"record_meta": true, "record_meta": true,
"initial": 0, "initial": 0,
@@ -86,65 +136,18 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"AVERAGE_NUM": { "EIS_AVERAGE_NUM": {
"description": "Number of sample used for average funciton", "description": "Number of sample used for average funciton",
"record_meta": true, "record_meta": true,
"initial": 8, "initial": 8,
"value": [ "value": [
2, 2,
4, 4,
8, 6,
16 8
]
},
"DC_BIAS": {
"description": "DC voltage bias in mV",
"record_meta": true,
"initial": 15000,
"domain": [
35001
],
"value": {
"expression": "VALUE"
}
},
"AC_AMP": {
"description": "AC Amplitude in mV",
"record_meta": true,
"initial": 25,
"domain": [
2048
]
},
"SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
},
"PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 10,
"domain": [
11
]
},
"RTIA": {
"description": "High speed tia gain",
"record_meta": true,
"initial": 4,
"value": [
0,
1,
2,
3,
4
] ]
}, },
"ADC_VALUE_I": { "ADC_VALUE_I": {
"description": "ADC value current value", "description": "ADC value current value",
"domain": "int" "domain": "int"
@@ -154,10 +157,10 @@
"record_meta": true, "record_meta": true,
"initial": 10000, "initial": 10000,
"domain": [ "domain": [
100001 100001
], ],
"value": { "value": {
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"CTRL_HIGH_Z_15": { "CTRL_HIGH_Z_15": {
@@ -192,8 +195,7 @@
"1", "1",
"2", "2",
"auto" "auto"
], ]
"on_change": "set_adc_gain_Vin"
}, },
"VOLT_INITIAL": { "VOLT_INITIAL": {
"description": "Initial Voltage of Scan", "description": "Initial Voltage of Scan",
@@ -239,12 +241,46 @@
"expression": "VALUE" "expression": "VALUE"
} }
}, },
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"MEASURE_VIN_RANGE": {
"description": "measure range of Vin",
"record_meta": true,
"initial": 0,
"value": [
"0",
"1",
"2",
"auto"
]
},
"RT_VOLT_SET": {
"description": "DAC output Voltage",
"record_meta": true,
"initial": 37500,
"domain": [
65536
],
"value": {
"expression": "VALUE"
},
"on_change": "set_para_RT_VOLT_SET"
},
"BLE_WRITE": { "BLE_WRITE": {
"description": "send msg to elite", "description": "send msg to elite",
"domain": { "domain": {
"list": [ "list": [
"BLE_WRITE_MAX" "BLE_WRITE_MAX"
] ]
}, },
"initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]", "initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
"value": "VALUE" "value": "VALUE"
@@ -259,7 +295,7 @@
{ {
"expression": "MODE", "expression": "MODE",
"when": { "when": {
"*": "start_data" "*": "start_data"
} }
} }
], ],
@@ -269,20 +305,21 @@
{ {
"expression": "MODE", "expression": "MODE",
"when": { "when": {
"1": "set_adc_gain_I" "0": "set_general_hs_rtia",
} "1": "set_adc_gain_I",
}, "2": "set_adc_gain_I",
{ "3": "set_adc_gain_I",
"expression": "MODE", "4": "set_adc_gain_I"
"when": {
"1": "set_adc_gain_Vin"
} }
}, },
{ {
"expression": "MODE", "expression": "MODE",
"when": { "when": {
"0": "curve_eis", "0": "curve_eis",
"1": "curve_cv3" "1": "curve_cv3",
"2": "curve_const_vscan",
"3": "curve_vt",
"4": "curve_rt"
} }
}, },
{ {
@@ -292,6 +329,12 @@
"1": "curve_cv3_para2" "1": "curve_cv3_para2"
} }
}, },
{
"expression": "MODE",
"when": {
"0": "curve_eis_mode"
}
},
"_sync(True)", "_sync(True)",
"VIS_STI" "VIS_STI"
], ],
@@ -309,6 +352,12 @@
"data_format_cali": [ "data_format_cali": [
"_data_format_cali('EISZeroOne')" "_data_format_cali('EISZeroOne')"
], ],
"set_general_hs_rtia": {
"type": "RIS",
"data": [
"1XFF;1X70;1B>GENERAL_HS_RTIA"
]
},
"set_sample_rate": { "set_sample_rate": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
@@ -324,12 +373,6 @@
"XE1;X05;B>ADC_LEVEL_I_15" "XE1;X05;B>ADC_LEVEL_I_15"
] ]
}, },
"set_adc_gain_Vin": {
"type": "RIS",
"data": [
"XE1;X06;B>ADC_LEVEL_V_IN_15"
]
},
"set_ctrl_highZ": { "set_ctrl_highZ": {
"type": "RIS", "type": "RIS",
"data": [ "data": [
@@ -339,35 +382,41 @@
"curve_eis": { "curve_eis": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"fa": "FREQ_START", "fa": "EIS_FREQ[0]",
"fb": "FREQ_STOP", "fb": "EIS_FREQ[1]",
"dp": "DELAY", "dp": "EIS_DELAY",
"dc": "DC_BIAS", "dc": "EIS_DC_BIAS",
"am": "AC_AMP", "am": "EIS_AC_AMP",
"an": "AVERAGE_NUM", "an": "EIS_AVERAGE_NUM",
"rt": "RTIA", "rt": "GENERAL_HS_RTIA",
"pp": "PPD", "pp": "EIS_PPD",
"sp": "SCALE" "sp": "EIS_SCALE"
}, },
"data": [ "data": [
"1XD1;1X01;4B>fa;4B>fb;2B>dp" "1X12;1X01;4B>fa;4B>fb;2B>dp"
] ]
}, },
"curve_eis_para2": { "curve_eis_para2": {
"type": "RIS", "type": "RIS",
"parameter": { "parameter": {
"fa": "FREQ_START", "fa": "EIS_FREQ[0]",
"fb": "FREQ_STOP", "fb": "EIS_FREQ[1]",
"dp": "DELAY", "dp": "EIS_DELAY",
"dc": "DC_BIAS", "dc": "EIS_DC_BIAS",
"am": "AC_AMP", "am": "EIS_AC_AMP",
"an": "AVERAGE_NUM", "an": "EIS_AVERAGE_NUM",
"rt": "RTIA", "rt": "GENERAL_HS_RTIA",
"pp": "PPD", "pp": "EIS_PPD",
"sp": "SCALE" "sp": "EIS_SCALE"
}, },
"data": [ "data": [
"1XD1;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp" "1X12;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_eis_mode": {
"type": "RIS",
"data": [
"1X12;1XFF"
] ]
}, },
"curve_cv3": { "curve_cv3": {
@@ -381,7 +430,7 @@
"cn": "CYCLE_NUMBER" "cn": "CYCLE_NUMBER"
}, },
"data": [ "data": [
"1XD2;1X01;2B>va;2B>vb;2B>vc;" "1X09;1X01;2B>va;2B>vb;2B>vc;"
] ]
}, },
"curve_cv3_para2": { "curve_cv3_para2": {
@@ -395,17 +444,66 @@
"cn": "CYCLE_NUMBER" "cn": "CYCLE_NUMBER"
}, },
"data": [ "data": [
"1XD2;1X02;4B>ve;2B>vf;2B>cn" "1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1X0B;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_rt": {
"type": "RIS",
"parameter": {
"va": "RT_VOLT_SET",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"X04;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_vt": {
"type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE",
"va": "MEASURE_VIN_RANGE"
},
"data": [
"X05;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe;",
"1B>va"
]
},
"set_para_RT_VOLT_SET": {
"type": "RIS",
"data": [
"XE2;X01;2B>RT_VOLT_SET"
] ]
}, },
"VIS_CC_ZERO": [
"_data_format('EISZeroOne')",
"_disable_cache(False)",
"_notify(True)",
"VIS_CC_ZERO",
"_sync(True)",
"VIS_STI"
],
"ble_instru_send": [ "ble_instru_send": [
"ble_write", "ble_write",
"_cdr('20X>ADC_VALUE_I')" "_cdr('20X>ADC_VALUE_I')"
@@ -430,4 +528,4 @@
"_cdr('20X>ADC_VALUE_I')" "_cdr('20X>ADC_VALUE_I')"
] ]
} }
} }
@@ -0,0 +1,531 @@
{
"name": "Elite_EIS_1.1",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite.*",
"major_product_number": 0,
"minor_product_number": 4,
"major_version_number": 1,
"minor_version_number": 1
},
"constant": {
"FREQ_MAX": 13333334,
"VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
},
"parameters": {
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"CHANNEL": {
"derzteription": "record channels",
"record_meta": true,
"domain": "property",
"value": "[0, 1, 2]"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
"record_meta": true,
"initial": 1000,
"domain": [
1001
],
"value": {
"expression": "VALUE"
},
"on_change": "set_sample_rate"
},
"AMP_GAIN": {
"description": "amp gain",
"record_meta": true,
"domain": "constant",
"value": 1
},
"MODE": {
"description": "working mode",
"record_meta": true,
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"V-T Graph",
"R-T Graph",
"Dev Mode"
]
},
"GENERAL_HS_RTIA": {
"description": "High speed rtia gain",
"record_meta": true,
"initial": 4,
"value": [
0,
1,
2,
3,
4
],
"on_change": "set_general_hs_rtia"
},
"EIS_DC_BIAS": {
"description": "DC voltage bias",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 25,
"domain": [
2048
]
},
"EIS_FREQ": {
"description": "[start, stop] of frequency scan",
"record_meta": true,
"initial": [
13333333,
7
],
"domain": {
"list": [
"FREQ_MAX"
]
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 10,
"domain": [
11
]
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
},
"EIS_DELAY": {
"description": "Wait x peroid before start taking measurements",
"record_meta": true,
"initial": 0,
"domain": [
101
],
"value": {
"expression": "VALUE"
}
},
"EIS_AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"record_meta": true,
"initial": 8,
"value": [
2,
4,
6,
8
]
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"Scan_Rate": {
"description": "Voltage Scan Rate",
"record_meta": true,
"initial": 10000,
"domain": [
100001
],
"value": {
"expression": "VALUE"
}
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
"initial": 1,
"value": [
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
},
"ADC_LEVEL_I_15": {
"description": "ADC level",
"record_meta": true,
"initial": 4,
"value": [
"0",
"1",
"2",
"3",
"auto"
],
"on_change": "set_adc_gain_I"
},
"ADC_LEVEL_V_IN_15": {
"description": "ADC level",
"record_meta": true,
"initial": 3,
"value": [
"0",
"1",
"2",
"auto"
]
},
"VOLT_INITIAL": {
"description": "Initial Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"VOLT_MAX": {
"description": "Max Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"VOLT_MIN": {
"description": "Min Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"record_meta": true,
"initial": 1,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"MEASURE_VIN_RANGE": {
"description": "measure range of Vin",
"record_meta": true,
"initial": 0,
"value": [
"0",
"1",
"2",
"auto"
]
},
"RT_VOLT_SET": {
"description": "DAC output Voltage",
"record_meta": true,
"initial": 37500,
"domain": [
65536
],
"value": {
"expression": "VALUE"
},
"on_change": "set_para_RT_VOLT_SET"
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
"list": [
"BLE_WRITE_MAX"
]
},
"initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
"value": "VALUE"
},
"BLE_READ": {
"description": "receive msg from elite",
"domain": "int"
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"*": "start_data"
}
}
],
"start_data": [
"data_format_cali",
"_notify(True)",
{
"expression": "MODE",
"when": {
"0": "set_general_hs_rtia",
"1": "set_adc_gain_I",
"2": "set_adc_gain_I",
"3": "set_adc_gain_I",
"4": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3",
"2": "curve_const_vscan",
"3": "curve_vt",
"4": "curve_rt"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis_para2",
"1": "curve_cv3_para2"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis_mode"
}
},
"_sync(True)",
"VIS_STI"
],
"data_format": [
"_data_format('EISZeroOne')",
{
"expression": "MODE",
"when": {
"0": "_disable_cache(True)",
"1": "_disable_cache(True)",
"*": "_disable_cache(False)"
}
}
],
"data_format_cali": [
"_data_format_cali('EISZeroOne')"
],
"set_general_hs_rtia": {
"type": "RIS",
"data": [
"1XFF;1X70;1B>GENERAL_HS_RTIA"
]
},
"set_sample_rate": {
"type": "RIS",
"parameter": {
"va": "SAMPLE_RATE"
},
"data": [
"XE0;2B>va"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
"XE1;X05;B>ADC_LEVEL_I_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
"XE1;X03;B>CTRL_HIGH_Z_15"
]
},
"curve_eis": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
},
"data": [
"1X12;1X01;4B>fa;4B>fb;2B>dp"
]
},
"curve_eis_para2": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
},
"data": [
"1X12;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_eis_mode": {
"type": "RIS",
"data": [
"1X12;1XFF"
]
},
"curve_cv3": {
"type": "RIS",
"parameter": {
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X01;2B>va;2B>vb;2B>vc;"
]
},
"curve_cv3_para2": {
"type": "RIS",
"parameter": {
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1X0B;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_rt": {
"type": "RIS",
"parameter": {
"va": "RT_VOLT_SET",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"X04;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_vt": {
"type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE",
"va": "MEASURE_VIN_RANGE"
},
"data": [
"X05;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe;",
"1B>va"
]
},
"set_para_RT_VOLT_SET": {
"type": "RIS",
"data": [
"XE2;X01;2B>RT_VOLT_SET"
]
},
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"
],
"ble_write": {
"type": "RIS",
"data": [
"XFF;",
"1B>BLE_WRITE[0];1B>BLE_WRITE[1];1B>BLE_WRITE[2];1B>BLE_WRITE[3];",
"1B>BLE_WRITE[4];1B>BLE_WRITE[5];1B>BLE_WRITE[6];1B>BLE_WRITE[7];",
"1B>BLE_WRITE[8];1B>BLE_WRITE[9];1B>BLE_WRITE[10];1B>BLE_WRITE[11];",
"1B>BLE_WRITE[12];1B>BLE_WRITE[13];1B>BLE_WRITE[14];1B>BLE_WRITE[15];",
"1B>BLE_WRITE[16];"
]
},
"dev_version": [
"CIS_VERSION",
"_cdr('20X>ADC_VALUE_I')"
],
"dev_battery": [
"CIS_VOLT",
"_cdr('20X>ADC_VALUE_I')"
]
}
}
@@ -0,0 +1,531 @@
{
"name": "Elite_EIS_MINI_1.0",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite.*",
"major_product_number": 0,
"minor_product_number": 4,
"major_version_number": 1,
"minor_version_number": 2
},
"constant": {
"FREQ_MAX": 13333334,
"VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
},
"parameters": {
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"CHANNEL": {
"derzteription": "record channels",
"record_meta": true,
"domain": "property",
"value": "[0, 1, 2]"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
"record_meta": true,
"initial": 1000,
"domain": [
1001
],
"value": {
"expression": "VALUE"
},
"on_change": "set_sample_rate"
},
"AMP_GAIN": {
"description": "amp gain",
"record_meta": true,
"domain": "constant",
"value": 1
},
"MODE": {
"description": "working mode",
"record_meta": true,
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"V-T Graph",
"R-T Graph",
"Dev Mode"
]
},
"GENERAL_HS_RTIA": {
"description": "High speed rtia gain",
"record_meta": true,
"initial": 4,
"value": [
0,
1,
2,
3,
4
],
"on_change": "set_general_hs_rtia"
},
"EIS_DC_BIAS": {
"description": "DC voltage bias",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 25,
"domain": [
2048
]
},
"EIS_FREQ": {
"description": "[start, stop] of frequency scan",
"record_meta": true,
"initial": [
13333333,
7
],
"domain": {
"list": [
"FREQ_MAX"
]
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 10,
"domain": [
11
]
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
},
"EIS_DELAY": {
"description": "Wait x peroid before start taking measurements",
"record_meta": true,
"initial": 0,
"domain": [
101
],
"value": {
"expression": "VALUE"
}
},
"EIS_AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"record_meta": true,
"initial": 8,
"value": [
2,
4,
6,
8
]
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"Scan_Rate": {
"description": "Voltage Scan Rate",
"record_meta": true,
"initial": 10000,
"domain": [
100001
],
"value": {
"expression": "VALUE"
}
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
"initial": 1,
"value": [
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
},
"ADC_LEVEL_I_15": {
"description": "ADC level",
"record_meta": true,
"initial": 4,
"value": [
"0",
"1",
"2",
"3",
"auto"
],
"on_change": "set_adc_gain_I"
},
"ADC_LEVEL_V_IN_15": {
"description": "ADC level",
"record_meta": true,
"initial": 3,
"value": [
"0",
"1",
"2",
"auto"
]
},
"VOLT_INITIAL": {
"description": "Initial Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"VOLT_MAX": {
"description": "Max Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"VOLT_MIN": {
"description": "Min Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"record_meta": true,
"initial": 1,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"MEASURE_VIN_RANGE": {
"description": "measure range of Vin",
"record_meta": true,
"initial": 0,
"value": [
"0",
"1",
"2",
"auto"
]
},
"RT_VOLT_SET": {
"description": "DAC output Voltage",
"record_meta": true,
"initial": 37500,
"domain": [
65536
],
"value": {
"expression": "VALUE"
},
"on_change": "set_para_RT_VOLT_SET"
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
"list": [
"BLE_WRITE_MAX"
]
},
"initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
"value": "VALUE"
},
"BLE_READ": {
"description": "receive msg from elite",
"domain": "int"
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"*": "start_data"
}
}
],
"start_data": [
"data_format_cali",
"_notify(True)",
{
"expression": "MODE",
"when": {
"0": "set_general_hs_rtia",
"1": "set_adc_gain_I",
"2": "set_adc_gain_I",
"3": "set_adc_gain_I",
"4": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3",
"2": "curve_const_vscan",
"3": "curve_vt",
"4": "curve_rt"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis_para2",
"1": "curve_cv3_para2"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis_mode"
}
},
"_sync(True)",
"VIS_STI"
],
"data_format": [
"_data_format('EISZeroOne')",
{
"expression": "MODE",
"when": {
"0": "_disable_cache(True)",
"1": "_disable_cache(True)",
"*": "_disable_cache(False)"
}
}
],
"data_format_cali": [
"_data_format_cali('EISZeroOne')"
],
"set_general_hs_rtia": {
"type": "RIS",
"data": [
"1XFF;1X70;1B>GENERAL_HS_RTIA"
]
},
"set_sample_rate": {
"type": "RIS",
"parameter": {
"va": "SAMPLE_RATE"
},
"data": [
"XE0;2B>va"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
"XE1;X05;B>ADC_LEVEL_I_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
"XE1;X03;B>CTRL_HIGH_Z_15"
]
},
"curve_eis": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
},
"data": [
"1X12;1X01;4B>fa;4B>fb;2B>dp"
]
},
"curve_eis_para2": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
},
"data": [
"1X12;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_eis_mode": {
"type": "RIS",
"data": [
"1X12;1XFF"
]
},
"curve_cv3": {
"type": "RIS",
"parameter": {
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X01;2B>va;2B>vb;2B>vc;"
]
},
"curve_cv3_para2": {
"type": "RIS",
"parameter": {
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1X0B;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_rt": {
"type": "RIS",
"parameter": {
"va": "RT_VOLT_SET",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"X04;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"curve_vt": {
"type": "RIS",
"parameter": {
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE",
"va": "MEASURE_VIN_RANGE"
},
"data": [
"X05;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe;",
"1B>va"
]
},
"set_para_RT_VOLT_SET": {
"type": "RIS",
"data": [
"XE2;X01;2B>RT_VOLT_SET"
]
},
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"
],
"ble_write": {
"type": "RIS",
"data": [
"XFF;",
"1B>BLE_WRITE[0];1B>BLE_WRITE[1];1B>BLE_WRITE[2];1B>BLE_WRITE[3];",
"1B>BLE_WRITE[4];1B>BLE_WRITE[5];1B>BLE_WRITE[6];1B>BLE_WRITE[7];",
"1B>BLE_WRITE[8];1B>BLE_WRITE[9];1B>BLE_WRITE[10];1B>BLE_WRITE[11];",
"1B>BLE_WRITE[12];1B>BLE_WRITE[13];1B>BLE_WRITE[14];1B>BLE_WRITE[15];",
"1B>BLE_WRITE[16];"
]
},
"dev_version": [
"CIS_VERSION",
"_cdr('20X>ADC_VALUE_I')"
],
"dev_battery": [
"CIS_VOLT",
"_cdr('20X>ADC_VALUE_I')"
]
}
}
@@ -1,12 +1,12 @@
{ {
"name": "EliteZM_pulsefly", "name": "Elite_MEGAFLY_0.1",
"version": "1.2.30", "version": "1.2.30",
"match_rule": { "match_rule": {
"local_name_pattern": "Elite.*", "local_name_pattern": "Elite.*",
"major_product_number": 0, "major_product_number": 0,
"minor_product_number": 2, "minor_product_number": 6,
"major_version_number": 1, "major_version_number": 1,
"minor_version_number": 7 "minor_version_number": 0
}, },
"constant": { "constant": {
"ADC_CHANNEL_NUMBER": [ "ADC_CHANNEL_NUMBER": [
@@ -1426,14 +1426,6 @@
"X80;X03;B>CTRL_HIGH_Z_15" "X80;X03;B>CTRL_HIGH_Z_15"
] ]
}, },
"VIS_CC_ZERO": [
"_data_format('I4V4Z4T4')",
"_disable_cache(False)",
"_notify(True)",
"VIS_CC_ZERO",
"_sync(True)",
"VIS_STI"
],
"pulse_fly": [ "pulse_fly": [
"sti_mode", "sti_mode",
"gas1_mode", "gas1_mode",
@@ -1,5 +1,5 @@
{ {
"name": "Elite_TRI", "name": "Elite_TRIG_0.1",
"version": "1.2.30", "version": "1.2.30",
"match_rule": { "match_rule": {
"local_name_pattern": "Trigger.*", "local_name_pattern": "Trigger.*",
-221
View File
@@ -1,221 +0,0 @@
{
"name": "Elite",
"version": "0.1",
"match_rule": {
"local_name_pattern": "Elite.*",
"major_product_number": 0,
"minor_product_number": 1,
"major_version_number": 0,
"minor_version_number": 1
},
"constant": {
"REC_CHANNEL_COUNT": 16,
"STI_CHANNEL_COUNT": 15,
"ADC_SAMPLE_RATE_LIST": [
15,
25,
40,
50,
100,
250,
500,
1000,
2500,
4000,
5000
],
"STI_FREQ_LIST": [
15,
25,
40,
50,
100,
250,
500,
1000,
2500,
4000,
5000
]
},
"parameters": {
"MODE": {
"description": "working mode",
"value": [
"Recording Mode",
"Stimulation Mode",
"Artifact Mode"
]
},
"CHANNEL": {
"description": "record channels",
"record_meta": true,
"domain": {
"set": [
"REC_CHANNEL_COUNT"
]
}
},
"SAMPLE_RATE": {
"alias": "ADC_RATE",
"description": "sampling rate",
"record_meta": true,
"domain": [
"len(ADC_SAMPLE_RATE_LIST)"
],
"value": "ADC_SAMPLE_RATE_LIST[VALUE]"
},
"AMP_GAIN": {
"description": "",
"record_meta": true,
"value": [
400,
1000,
2000
]
},
"LOW_FREQ_BAND": {
"description": "",
"record_meta": true,
"domain": [
7
]
},
"STI_MODE": {
"description": "stimulation mode",
"value": [
"Positive Pulse",
"Negative Pulse",
"Pos to Neg Pulse",
"Neg to Pos Pulse",
"Arbitrary Waveform"
]
},
"STI_VOLT": {
"description": "stimulation voltage",
"domain": [
32
],
"value": "2 + 3 * VALUE / 31"
},
"STI_FREQ": {
"description": "stimulation frequency",
"domain": [
"len(STI_FREQ_LIST)"
],
"value": "STI_FREQ_LIST[VALUE]"
},
"STI_PMOS": {
"description": "stimulation PMOS channel",
"initial": 0,
"domain": [
"STI_CHANNEL_COUNT"
],
"guard": "STI_PMOS != STI_NMOS"
},
"STI_NMOS": {
"description": "stimulation NMOS channel",
"initial": "STI_CHANNEL_COUNT - 1",
"domain": [
"STI_CHANNEL_COUNT"
],
"guard": "STI_PMOS != STI_NMOS"
},
"CHOPPER": {
"description": "",
"domain": "bool"
},
"FAST_SETTLE": {
"description": "",
"domain": "bool"
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"0": "start_recording",
"1": "start_stimulation",
"2": "start_artifact"
}
},
"VIS_STI"
],
"start_recording": [
{
"expression": "len(CHANNEL) > 0",
"raise": "no recording channel"
},
"data_format",
"_notify(True)",
"start_recording0",
"_sync(True)"
],
"start_artifact": [
{
"expression": "len(CHANNEL) > 0",
"raise": "no recording channel"
},
"data_format",
"_notify(True)",
"start_artifact0",
"_sync(True)"
],
"data_format": [
"_data_format('TDC4VAF2')"
],
"start_recording0": {
"type": "RIS",
"foreach-parameter": {
"parameter": "CHANNEL",
"variable": [
"a",
"b",
"c",
"d"
]
},
"data": [
"3b110#recording header;2b<AMP_GAIN;3b<LOW_FREQ_BAND",
"4b>SAMPLE_RATE;1ba?;1bb?;1bc?;1bd?",
"4b<a?:0;4b<b?:0",
"4b<c?:0;4b<d?:0"
]
},
"start_artifact0": {
"type": "RIS",
"foreach-parameter": {
"parameter": "CHANNEL",
"variable": [
"a",
"b",
"c",
"d"
]
},
"data": [
"3b100#artifact mode header;2b0;3b001",
"4b>SAMPLE_RATE;1ba?;1bb?;1bc?;1bd?",
"4b<a?:0;4b<b?:0",
"4b<c?:0;4b<d?:0"
]
},
"start_stimulation": [
"start_stimulation0"
],
"start_stimulation0": {
"type": "RIS",
"guard": {
"expression": "STI_PMOS != STI_NMOS",
"raise": "same N/PMos channel"
},
"data": [
"3b111#stimulation header;2b0;3bSTI_MODE",
"4b>STI_FREQ;1bCHOPPER;1bFAST_SETTLE;2b0",
"4b<STI_PMOS;4b<STI_NMOS",
"5b<STI_VOLT;3b0"
]
}
}
}
@@ -1,220 +0,0 @@
{
"name": "Elite_Legacy",
"version": "0.0.0",
"match_rule": {
"major_product_number": 0,
"minor_product_number": 0,
"major_version_number": 0,
"minor_version_number": 0
},
"constant": {
"REC_CHANNEL_COUNT": 16,
"STI_CHANNEL_COUNT": 15,
"ADC_SAMPLE_RATE_LIST": [
15,
25,
40,
50,
100,
250,
500,
1000,
2500,
4000,
5000
],
"STI_FREQ_LIST": [
15,
25,
40,
50,
100,
250,
500,
1000,
2500,
4000,
5000
]
},
"parameters": {
"MODE": {
"description": "working mode",
"value": [
"Recording Mode",
"Stimulation Mode",
"Artifact Mode"
]
},
"CHANNEL": {
"description": "record channels",
"record_meta": true,
"domain": {
"set": [
"REC_CHANNEL_COUNT"
]
}
},
"SAMPLE_RATE": {
"alias": "ADC_RATE",
"description": "sampling rate",
"record_meta": true,
"domain": [
"len(ADC_SAMPLE_RATE_LIST)"
],
"value": "ADC_SAMPLE_RATE_LIST[VALUE]"
},
"AMP_GAIN": {
"description": "",
"record_meta": true,
"value": [
400,
1000,
2000
]
},
"LOW_FREQ_BAND": {
"description": "",
"record_meta": true,
"domain": [
7
]
},
"STI_MODE": {
"description": "stimulation mode",
"value": [
"Positive Pulse",
"Negative Pulse",
"Pos to Neg Pulse",
"Neg to Pos Pulse",
"Arbitrary Waveform"
]
},
"STI_VOLT": {
"description": "stimulation voltage",
"domain": [
32
],
"value": "2 + 3 * VALUE / 31"
},
"STI_FREQ": {
"description": "stimulation frequency",
"domain": [
"len(STI_FREQ_LIST)"
],
"value": "STI_FREQ_LIST[VALUE]"
},
"STI_PMOS": {
"description": "stimulation PMOS channel",
"initial": 0,
"domain": [
"STI_CHANNEL_COUNT"
],
"guard": "STI_PMOS != STI_NMOS"
},
"STI_NMOS": {
"description": "stimulation NMOS channel",
"initial": "STI_CHANNEL_COUNT - 1",
"domain": [
"STI_CHANNEL_COUNT"
],
"guard": "STI_PMOS != STI_NMOS"
},
"CHOPPER": {
"description": "",
"domain": "bool"
},
"FAST_SETTLE": {
"description": "",
"domain": "bool"
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"0": "start_recording",
"1": "start_stimulation",
"2": "start_artifact"
}
},
"VIS_STI"
],
"start_recording": [
{
"expression": "len(CHANNEL) > 0",
"raise": "no recording channel"
},
"data_format",
"_notify(True)",
"start_recording0",
"_sync(True)"
],
"start_artifact": [
{
"expression": "len(CHANNEL) > 0",
"raise": "no recording channel"
},
"data_format",
"_notify(True)",
"start_artifact0",
"_sync(True)"
],
"data_format": [
"_data_format('TC4VAF2')"
],
"start_recording0": {
"type": "RIS",
"foreach-parameter": {
"parameter": "CHANNEL",
"variable": [
"a",
"b",
"c",
"d"
]
},
"data": [
"3b110#recording header;2b<AMP_GAIN;3b<LOW_FREQ_BAND",
"4b>SAMPLE_RATE;1ba?;1bb?;1bc?;1bd?",
"4b<a?:0;4b<b?:0",
"4b<c?:0;4b<d?:0"
]
},
"start_artifact0": {
"type": "RIS",
"foreach-parameter": {
"parameter": "CHANNEL",
"variable": [
"a",
"b",
"c",
"d"
]
},
"data": [
"3b100#artifact mode header;2b0;3b001",
"4b>SAMPLE_RATE;1ba?;1bb?;1bc?;1bd?",
"4b<a?:0;4b<b?:0",
"4b<c?:0;4b<d?:0"
]
},
"start_stimulation": [
"start_stimulation0"
],
"start_stimulation0": {
"type": "RIS",
"guard": {
"expression": "STI_PMOS != STI_NMOS",
"raise": "same N/PMos channel"
},
"data": [
"3b111#stimulation header;2b0;3bSTI_MODE",
"4b>STI_FREQ;1bCHOPPER;1bFAST_SETTLE;2b0",
"4b<STI_PMOS;4b<STI_NMOS",
"5b<STI_VOLT;3b0"
]
}
}
}
-343
View File
@@ -1,343 +0,0 @@
{
"name": "EliteZM",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite-ZM.+",
"major_product_number": 0,
"minor_product_number": 2,
"major_version_number": 1,
"minor_version_number": 2
},
"constant": {
"ADC_CHANNEL_NUMBER": [
12,
13,
14,
15
],
"VOLT_MAX": 65536,
"STEP_MAX": 100,
"Const_Current_Range": 1500001
},
"parameters": {
"CHANNEL": {
"description": "record channels",
"record_meta": true,
"domain": "property",
"value": "[0, 1, 2]"
},
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
"record_meta": true,
"value": [
100,
10,
5,
1,
0.1,
0.01
],
"on_change": "set_sample_rate"
},
"AMP_GAIN": {
"description": "amp gain",
"record_meta": true,
"domain": "constant",
"value": 1
},
"MODE": {
"description": "working mode",
"record_meta": true,
"value": [
"I-V Curve",
"Cyclic Voltammetry",
"Function Generator",
"R-T Curve",
"V-T Curve",
"I-T Curve",
"ADC test",
"Constant Current"
]
},
"VOLT_ORIGIN": {
"description": "Origin Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "(VALUE) * 0x0001"
}
},
"VOLT_FINAL": {
"description": "The last Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": " (VALUE) * 0x0001"
}
},
"VOLT_STEP": {
"description": "Voltage Step",
"record_meta": true,
"initial": 0,
"domain": [
"STEP_MAX"
],
"value": {
"expression": "(VALUE + 1) * 0x0001"
}
},
"STEP_TIME": {
"description": "How much time between two step",
"record_meta": true,
"initial": 1,
"value": [
0.5,
1.0,
2.0
]
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"record_meta": true,
"initial": 0,
"domain": [
200
],
"value": {
"expression": "VALUE + 1"
}
},
"DAC_VOLT": {
"description": "DAC output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
]
},
"ADC_CHANNEL": {
"description": "read ADC data",
"record_meta": true,
"value": [
"ANA0",
"ANA1",
"ANA2",
"ANA3"
]
},
"ADC_LEVEL": {
"description": "ADC level",
"record_meta": true,
"initial": 3,
"value": [
"200k",
"10k",
"200R",
"auto"
],
"on_change": "set_adc_gain"
},
"Resister_LEVEL": {
"description": "Resister_LEVEL",
"record_meta": true,
"initial": 3,
"value": [
"Small",
"Middle",
"Large",
"Auto"
],
"on_change": "set_Resister_level"
},
"ADC_VALUE_V": {
"description": "ADC value voltage value",
"domain": "int"
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"Const_Current_unit": {
"description": "Constant Current unit Setting",
"initial": 1,
"value": [
"uA",
"mA"
]
},
"Const_Current_value": {
"description": "Constant Current value Setting",
"initial": 0,
"domain": [
"Const_Current_Range"
],
"value": {
"expression": "(VALUE) * 0x00000001"
}
},
"Charge": {
"description": "Charge battery or not",
"initial": 0,
"value": [
"Charge",
"Discharge"
]
},
"Const_Current_VStop": {
"description": "Constant Current Stopping Voltage",
"initial": 0,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "(VALUE) * 0x0001"
}
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"2": "start_fun_gen",
"6": "adc_test",
"*": "start_data"
}
}
],
"start_fun_gen": [
"data_format",
"func_gen",
"VIS_STI"
],
"adc_test": [
"adc_test0",
"_cdr('1X;4X>ADC_VALUE_I;4X>ADC_VALUE_V')"
],
"start_data": [
"data_format",
"_notify(True)",
"set_sample_rate",
{
"expression": "MODE",
"when": {
"0": "curve_iv",
"1": "curve_cv",
"3": "curve_zt",
"4": "curve_vt",
"5": "curve_it",
"7": "const_current"
}
},
"_sync(True)",
"VIS_STI"
],
"data_format": [
"_data_format('I4V4Z4T4')",
{
"expression": "MODE",
"when": {
"0": "_disable_cache(True)",
"1": "_disable_cache(True)",
"*": "_disable_cache(False)"
}
}
],
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN) * 0x0001",
"vb": "(VOLT_FINAL) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12"
},
"data": [
"1X10;2B>va;2B>vb;2B>dv;B>dt"
]
},
"curve_cv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN) * 0x0001",
"vb": "(VOLT_FINAL) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12",
"cn": "CYCLE_NUMBER+1"
},
"data": [
"1X20;2B>va;2B>vb;2B>dv;B>dt;B>cn"
]
},
"func_gen": {
"type": "RIS",
"parameter": {
"v": "(DAC_VOLT) * 0x0001"
},
"data": [
"X30;2B>v"
]
},
"curve_zt": {
"type": "RIS",
"data": [
"X40"
]
},
"curve_vt": {
"type": "RIS",
"data": [
"X50"
]
},
"curve_it": {
"type": "RIS",
"data": [
"X60"
]
},
"adc_test0": {
"type": "RIS",
"data": [
"X90;B>ADC_LEVEL;B>ADC_CHANNEL"
]
},
"set_sample_rate": {
"type": "RIS",
"data": [
"X70;B>SAMPLE_RATE"
]
},
"set_adc_gain": {
"type": "RIS",
"data": [
"X80;B>ADC_LEVEL"
]
},
"set_Resister_level": {
"type": "RIS",
"data": [
"XE0;B>Resister_LEVEL"
]
},
"const_current": {
"type": "RIS",
"data": [
"XD0;B>Charge;2X>Const_Current_VStop;4X>Const_Current_value"
]
}
}
}
@@ -1,320 +0,0 @@
{
"name": "EliteZML",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite-ZM.+",
"major_product_number": 0,
"minor_product_number": 2,
"major_version_number": 1,
"minor_version_number": 4
},
"constant": {
"ADC_CHANNEL_NUMBER": [
12,
13,
14,
15
],
"VOLT_MAX": 65536,
"STEP_MAX": 100,
"Const_Current_Range": 3000001
},
"parameters": {
"CHANNEL": {
"description": "record channels",
"record_meta": true,
"domain": "property",
"value": "[0, 1, 2]"
},
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
"record_meta": true,
"value": [
100,
10,
5,
1,
0.1,
0.01
],
"on_change": "set_sample_rate"
},
"AMP_GAIN": {
"description": "amp gain",
"record_meta": true,
"domain": "constant",
"value": 1
},
"MODE": {
"description": "working mode",
"record_meta": true,
"value": [
"I-V Curve",
"Cyclic Voltammetry",
"Function Generator",
"R-T Curve",
"V-T Curve",
"I-T Curve",
"ADC test",
"Constant Current"
]
},
"VOLT_ORIGIN": {
"description": "Origin Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "(VALUE + 1) * 0x0001"
}
},
"VOLT_FINAL": {
"description": "The last Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": " (VALUE + 1) * 0x0001"
}
},
"VOLT_STEP": {
"description": "Voltage Step",
"record_meta": true,
"initial": 0,
"domain": [
"STEP_MAX"
],
"value": {
"expression": "(VALUE + 1) * 0x0001"
}
},
"STEP_TIME": {
"description": "How much time between two step",
"record_meta": true,
"initial": 1,
"value": [
0.5,
1.0,
2.0
]
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"record_meta": true,
"domain": [
200
],
"value": {
"expression": "VALUE + 1"
}
},
"DAC_VOLT": {
"description": "DAC output Voltage",
"record_meta": true,
"domain": [
65536
]
},
"ADC_CHANNEL": {
"description": "read ADC data",
"record_meta": true,
"value": [
"ANA0",
"ANA1",
"ANA2",
"ANA3"
]
},
"ADC_LEVEL": {
"description": "ADC level",
"record_meta": true,
"value": [
"200k",
"10k",
"200R",
"auto"
],
"on_change": "set_adc_gain"
},
"Resister_LEVEL": {
"description": "Resister_LEVEL",
"record_meta": true,
"value": [
"Small",
"Middle",
"Large",
"Auto"
],
"on_change": "set_Resister_level"
},
"ADC_VALUE_V": {
"description": "ADC value voltage value",
"domain": "int"
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"Const_Current_unit": {
"description": "Constant Current unit Setting",
"value": [
"uA",
"mA"
]
},
"Const_Current_value": {
"description": "Constant Current value Setting",
"initial": 1500000,
"domain": [
"Const_Current_Range"
],
"value": {
"expression": "(VALUE) * 0x00000001"
}
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"2": "start_fun_gen",
"6": "adc_test",
"*": "start_data"
}
}
],
"start_fun_gen": [
"data_format",
"func_gen",
"VIS_STI"
],
"adc_test": [
"adc_test0",
"_cdr('1X;4X>ADC_VALUE_I;4X>ADC_VALUE_V')"
],
"start_data": [
"data_format",
"_notify(True)",
"set_sample_rate",
{
"expression": "MODE",
"when": {
"0": "curve_iv",
"1": "curve_cv",
"3": "curve_zt",
"4": "curve_vt",
"5": "curve_it",
"7": "const_current"
}
},
"_sync(True)",
"VIS_STI"
],
"data_format": [
"_data_format('I4V4Z4T4')",
{
"expression": "MODE",
"when": {
"0": "_disable_cache(True)",
"1": "_disable_cache(True)",
"*": "_disable_cache(False)"
}
}
],
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN + 1) * 0x0001",
"vb": "(VOLT_FINAL + 1) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12"
},
"data": [
"1X10;2B>va;2B>vb;2B>dv;B>dt"
]
},
"curve_cv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN + 1) * 0x0001",
"vb": "(VOLT_FINAL + 1) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12",
"cn": "CYCLE_NUMBER+1"
},
"data": [
"1X20;2B>va;2B>vb;2B>dv;B>dt;B>CYCLE_NUMBER"
]
},
"func_gen": {
"type": "RIS",
"parameter": {
"v": "(DAC_VOLT) * 0x0001"
},
"data": [
"X30;2B>v"
]
},
"curve_zt": {
"type": "RIS",
"data": [
"X40"
]
},
"curve_vt": {
"type": "RIS",
"data": [
"X50"
]
},
"curve_it": {
"type": "RIS",
"data": [
"X60"
]
},
"adc_test0": {
"type": "RIS",
"data": [
"X90;B>ADC_LEVEL;B>ADC_CHANNEL"
]
},
"set_sample_rate": {
"type": "RIS",
"data": [
"X70;B>SAMPLE_RATE"
]
},
"set_adc_gain": {
"type": "RIS",
"data": [
"X80;B>ADC_LEVEL"
]
},
"set_Resister_level": {
"type": "RIS",
"data": [
"XE0;B>Resister_LEVEL"
]
},
"const_current": {
"type": "RIS",
"data": [
"XD0;4X>Const_Current_value"
]
}
}
}
@@ -1,320 +0,0 @@
{
"name": "EliteZMS",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite-ZM.+",
"major_product_number": 0,
"minor_product_number": 2,
"major_version_number": 1,
"minor_version_number": 3
},
"constant": {
"ADC_CHANNEL_NUMBER": [
12,
13,
14,
15
],
"VOLT_MAX": 65536,
"STEP_MAX": 100,
"Const_Current_Range": 3000001
},
"parameters": {
"CHANNEL": {
"description": "record channels",
"record_meta": true,
"domain": "property",
"value": "[0, 1, 2]"
},
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
"record_meta": true,
"value": [
100,
10,
5,
1,
0.1,
0.01
],
"on_change": "set_sample_rate"
},
"AMP_GAIN": {
"description": "amp gain",
"record_meta": true,
"domain": "constant",
"value": 1
},
"MODE": {
"description": "working mode",
"record_meta": true,
"value": [
"I-V Curve",
"Cyclic Voltammetry",
"Function Generator",
"R-T Curve",
"V-T Curve",
"I-T Curve",
"ADC test",
"Constant Current"
]
},
"VOLT_ORIGIN": {
"description": "Origin Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "(VALUE + 1) * 0x0001"
}
},
"VOLT_FINAL": {
"description": "The last Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": " (VALUE + 1) * 0x0001"
}
},
"VOLT_STEP": {
"description": "Voltage Step",
"record_meta": true,
"initial": 0,
"domain": [
"STEP_MAX"
],
"value": {
"expression": "(VALUE + 1) * 0x0001"
}
},
"STEP_TIME": {
"description": "How much time between two step",
"record_meta": true,
"initial": 1,
"value": [
0.5,
1.0,
2.0
]
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"record_meta": true,
"domain": [
200
],
"value": {
"expression": "VALUE + 1"
}
},
"DAC_VOLT": {
"description": "DAC output Voltage",
"record_meta": true,
"domain": [
65536
]
},
"ADC_CHANNEL": {
"description": "read ADC data",
"record_meta": true,
"value": [
"ANA0",
"ANA1",
"ANA2",
"ANA3"
]
},
"ADC_LEVEL": {
"description": "ADC level",
"record_meta": true,
"value": [
"200k",
"10k",
"200R",
"auto"
],
"on_change": "set_adc_gain"
},
"Resister_LEVEL": {
"description": "Resister_LEVEL",
"record_meta": true,
"value": [
"Small",
"Middle",
"Large",
"Auto"
],
"on_change": "set_Resister_level"
},
"ADC_VALUE_V": {
"description": "ADC value voltage value",
"domain": "int"
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"Const_Current_unit": {
"description": "Constant Current unit Setting",
"value": [
"uA",
"mA"
]
},
"Const_Current_value": {
"description": "Constant Current value Setting",
"initial": 1500000,
"domain": [
"Const_Current_Range"
],
"value": {
"expression": "(VALUE) * 0x00000001"
}
}
},
"instruction": {
"start": [
{
"expression": "MODE",
"when": {
"2": "start_fun_gen",
"6": "adc_test",
"*": "start_data"
}
}
],
"start_fun_gen": [
"data_format",
"func_gen",
"VIS_STI"
],
"adc_test": [
"adc_test0",
"_cdr('1X;4X>ADC_VALUE_I;4X>ADC_VALUE_V')"
],
"start_data": [
"data_format",
"_notify(True)",
"set_sample_rate",
{
"expression": "MODE",
"when": {
"0": "curve_iv",
"1": "curve_cv",
"3": "curve_zt",
"4": "curve_vt",
"5": "curve_it",
"7": "const_current"
}
},
"_sync(True)",
"VIS_STI"
],
"data_format": [
"_data_format('I4V4Z4T4')",
{
"expression": "MODE",
"when": {
"0": "_disable_cache(True)",
"1": "_disable_cache(True)",
"*": "_disable_cache(False)"
}
}
],
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN + 1) * 0x0001",
"vb": "(VOLT_FINAL + 1) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12"
},
"data": [
"1X10;2B>va;2B>vb;2B>dv;B>dt"
]
},
"curve_cv": {
"type": "RIS",
"parameter": {
"va": "(VOLT_ORIGIN + 1) * 0x0001",
"vb": "(VOLT_FINAL + 1) * 0x0001",
"dv": "(VOLT_STEP + 1) * 0x0001",
"dt": "STEP_TIME * 0x12",
"cn": "CYCLE_NUMBER+1"
},
"data": [
"1X20;2B>va;2B>vb;2B>dv;B>dt;B>CYCLE_NUMBER"
]
},
"func_gen": {
"type": "RIS",
"parameter": {
"v": "(DAC_VOLT) * 0x0001"
},
"data": [
"X30;2B>v"
]
},
"curve_zt": {
"type": "RIS",
"data": [
"X40"
]
},
"curve_vt": {
"type": "RIS",
"data": [
"X50"
]
},
"curve_it": {
"type": "RIS",
"data": [
"X60"
]
},
"adc_test0": {
"type": "RIS",
"data": [
"X90;B>ADC_LEVEL;B>ADC_CHANNEL"
]
},
"set_sample_rate": {
"type": "RIS",
"data": [
"X70;B>SAMPLE_RATE"
]
},
"set_adc_gain": {
"type": "RIS",
"data": [
"X80;B>ADC_LEVEL"
]
},
"set_Resister_level": {
"type": "RIS",
"data": [
"XE0;B>Resister_LEVEL"
]
},
"const_current": {
"type": "RIS",
"data": [
"XD0;4X>Const_Current_value"
]
}
}
}
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
find /home/pi -maxdepth 1 -type f -iname '*.out' -mtime +30 -delete