Compare commits
200 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58bfc86572 | |||
| febba59c37 | |||
| b8f39e984b | |||
| 59585507a5 | |||
| f9f15457cf | |||
| cf62cfbe04 | |||
| 33697af99c | |||
| 985e043ca5 | |||
| 8fd119f4f0 | |||
| b5bd64bf6c | |||
| 241296f36c | |||
| f46073a46a | |||
| 24fd5ca28b | |||
| 288f261abe | |||
| a32267f1fd | |||
| c89c6e88d0 | |||
| 536bc23896 | |||
| 7deb709946 | |||
| 25267411d8 | |||
| 200feead76 | |||
| f445550b4e | |||
| dfbbfe4e07 | |||
| 57e5c1a9e2 | |||
| ba192ccce8 | |||
| aae1ab7a33 | |||
| 59148cff6d | |||
| c9b10fc6aa | |||
| f82c3ab033 | |||
| 3884fad006 | |||
| 75ca525f36 | |||
| 9bb947f8e0 | |||
| fc4f931f9d | |||
| 57ba7ed94f | |||
| cf8433c7ee | |||
| 4d1eee6893 | |||
| 7a77c4d413 | |||
| 6f8d68f476 | |||
| 8ae45d3b50 | |||
| 5e4980a1d5 | |||
| 7716908a3b | |||
| 813ff7bc7d | |||
| c2224ed624 | |||
| 72943c3b6f | |||
| 4d47d07996 | |||
| 2fdcef998f | |||
| 2b6381fa46 | |||
| c29d9729ba | |||
| 001905ec96 | |||
| 5033381e64 | |||
| aa88201a93 | |||
| c02c59345b | |||
| 0386cf1847 | |||
| 62d8610191 | |||
| 991f5d06ea | |||
| 55711285e6 | |||
| 3ec5fee43b | |||
| 614a9c0b0f | |||
| 22eb8a09f4 | |||
| dbd7431124 | |||
| 15c15275a7 | |||
| 836d75b77e | |||
| 417bdd91a4 | |||
| 62ee763e2c | |||
| 44e9e4cb67 | |||
| 38537563fd | |||
| 375372996d | |||
| d79491db8b | |||
| 5a35da98ac | |||
| 9c054bd733 | |||
| 64412f9376 | |||
| 97034d6b32 | |||
| f065bad826 | |||
| 9c1dafd003 | |||
| 03443ada99 | |||
| 17dc5470e7 | |||
| 695f37c2dd | |||
| 690f859e86 | |||
| 0ed4d0594a | |||
| 959d86c0fe | |||
| 24c07a7fa5 | |||
| e43857a5bc | |||
| c084f29f06 | |||
| 130d260add | |||
| 575d5d8af1 | |||
| fbf6297047 | |||
| c540013d19 | |||
| 7f0b00a323 | |||
| 4828c85668 | |||
| 4ce9fe5b8d | |||
| d74f09254e | |||
| 79ecff69cc | |||
| df45126ead | |||
| 9fade3469a | |||
| a77331176c | |||
| 8f98337267 | |||
| 205d39cb11 | |||
| a5ea3243fa | |||
| 2edf28c7ba | |||
| 5531dcc0f0 | |||
| b20d46daa8 | |||
| 789d9b3a81 | |||
| 0d0427ed14 | |||
| d434509c5b | |||
| 787d76d48c | |||
| 50f2432088 | |||
| 1cff19ac58 | |||
| baef447c0e | |||
| ee9c13d4c5 | |||
| 9076f2f10b | |||
| 9b2e2964b0 | |||
| 2622109c89 | |||
| a3fe6b87af | |||
| 64419ca1c5 | |||
| 7d77c44741 | |||
| 29b4dd5cc7 | |||
| f151ae6fce | |||
| e535e3d2b1 | |||
| 06c36aa737 | |||
| 402022c451 | |||
| c0bb567bf7 | |||
| 4daff72d39 | |||
| f99719832a | |||
| 58e09bfcda | |||
| 55780514b9 | |||
| 936514871f | |||
| f25d9221c6 | |||
| 2ee9fa6b19 | |||
| fcc39dbfed | |||
| e2f7bba961 | |||
| 1174d54bc0 | |||
| bff75dc49e | |||
| 35912f614e | |||
| cfc4e39c8a | |||
| 8c4916d1e8 | |||
| e3c252f204 | |||
| c2164da48b | |||
| ab2d746afb | |||
| 8a870a860a | |||
| f4c5cf0135 | |||
| 1f01fd3b9b | |||
| d1fe388c27 | |||
| 91d5e73c5e | |||
| d1b6c2892f | |||
| 4243a13536 | |||
| 97188abff8 | |||
| 9d8178d11a | |||
| bbde653a8e | |||
| 6c0cef7925 | |||
| 3bbf0c912a | |||
| 4333958ebe | |||
| 3239a691e3 | |||
| 30183788d8 | |||
| 13df921b1c | |||
| d182a04ed3 | |||
| 35a09ff9a0 | |||
| e134b9780c | |||
| df39f241b3 | |||
| 0b72ac0c9d | |||
| 0afbe66229 | |||
| 9846cfd708 | |||
| b4ad2a7fba | |||
| 675fdc2226 | |||
| a847b1222d | |||
| bd0c36923a | |||
| 612785f51a | |||
| 7dbf09e9a5 | |||
| ee64d43de1 | |||
| 60b91f0c1e | |||
| 8ac01bdf54 | |||
| 0f90b16b6e | |||
| cd98a14e84 | |||
| 2e97ad23eb | |||
| e0dd5a6972 | |||
| 76e0a150d1 | |||
| ecd4b9325d | |||
| 978b1254f0 | |||
| 26e02f2d40 | |||
| ead98fe8da | |||
| 257958768f | |||
| dc4e1bd233 | |||
| 42025d2243 | |||
| b341dbf073 | |||
| 20f6f126b0 | |||
| bf4a00db1a | |||
| 0b7a650b95 | |||
| 062613c681 | |||
| bffaff310b | |||
| 06bf262d59 | |||
| b2f9d98336 | |||
| a6b523404b | |||
| 6c232b3b07 | |||
| cfc2bf1d83 | |||
| 2b60e68197 | |||
| efb5e9aeb6 | |||
| b4d88a0e67 | |||
| 6029ff6fe1 | |||
| 6efc5e1097 | |||
| a23394d3d1 | |||
| c96f76f438 | |||
| f0f1c9fc49 |
@@ -7,3 +7,4 @@
|
||||
/.vscode
|
||||
/media
|
||||
python/biopro/sever/_identify.py
|
||||
*.log
|
||||
|
||||
@@ -78,6 +78,8 @@ add ssh.txt in boot folder
|
||||
|
||||
###### Install dependencies
|
||||
sudo apt-get install vim git wiringpi build-essential libi2c-dev i2c-tools python-dev libffi-dev python3-pip postgresql npm
|
||||
sudo apt-get install libatlas-base-dev
|
||||
sudo apt-get install python3-numpy
|
||||
|
||||
###### wiringpi conflict
|
||||
need to install wiringpi: https://github.com/WiringPi/WiringPi
|
||||
@@ -94,6 +96,7 @@ git clone https://gitlab.com/wisetop/controller/wisetopdataserver.git
|
||||
```
|
||||
cd ~/wisetopdataserver
|
||||
pip3 install -r requirements.txt
|
||||
pip3 install SQLAlchemy
|
||||
```
|
||||
##### Packages version
|
||||
```
|
||||
@@ -155,8 +158,8 @@ reboot
|
||||
|
||||
###### Set pi password
|
||||
```
|
||||
$cd ~
|
||||
$passwd
|
||||
cd ~
|
||||
passwd
|
||||
Current password:raspberry
|
||||
New password:5k6zj454778225
|
||||
Retype new password:5k6zj454778225
|
||||
@@ -195,11 +198,11 @@ exit 0
|
||||
### MQTT broker install
|
||||
|
||||
###### 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
|
||||
sudo vim /etc/mosquitto/conf.d/default.conf
|
||||
|
||||
add the code following as:
|
||||
```
|
||||
@@ -210,13 +213,13 @@ protocol websockets
|
||||
allow_anonymous true
|
||||
```
|
||||
###### 3.restart mqtt broker
|
||||
$sudo systemctl restart mosquitto
|
||||
sudo systemctl restart mosquitto
|
||||
|
||||
###### 4.Robust MQTT
|
||||
create mosquitto_restart.sh
|
||||
|
||||
$cd ~
|
||||
$sudo vim mosquitto_restart.sh
|
||||
cd ~
|
||||
sudo vim mosquitto_restart.sh
|
||||
|
||||
|
||||
add the code following as:
|
||||
@@ -233,16 +236,16 @@ echo "$SERVICE is currently running" >> /home/ubuntu/cron.log
|
||||
exit 0
|
||||
```
|
||||
###### 5.add mosquitto_restart.sh to root routing
|
||||
$sudo chmod +x mosquitto_restart.sh
|
||||
$sudo -i
|
||||
$crontab -e
|
||||
sudo chmod +x mosquitto_restart.sh
|
||||
sudo -i
|
||||
crontab -e
|
||||
|
||||
add the code following as:
|
||||
```
|
||||
*/5 * * * * /home/pi/mosquitto_restart.sh
|
||||
```
|
||||
###### 6.Auto run MQTT broker when when pi-start
|
||||
$sudo vim /etc/rc.local
|
||||
sudo vim /etc/rc.local
|
||||
|
||||
add the code following as:
|
||||
```
|
||||
@@ -251,31 +254,31 @@ sudo nohup systemctl restart mosquitto
|
||||
|
||||
### 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
|
||||
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
|
||||
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
|
||||
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 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
|
||||
sudo nano /etc/dnsmasq.conf
|
||||
|
||||
```
|
||||
interface=wlan0 # Listening interface
|
||||
@@ -286,10 +289,10 @@ address=/gw.wlan/192.168.2.1
|
||||
# Alias for this router
|
||||
```
|
||||
###### 3.Ensure Wireless Operation
|
||||
$sudo rfkill unblock wlan
|
||||
sudo rfkill unblock wlan
|
||||
|
||||
###### 4.Configure the AP Software
|
||||
$sudo nano /etc/hostapd/hostapd.conf
|
||||
sudo nano /etc/hostapd/hostapd.conf
|
||||
|
||||
```
|
||||
country_code=TW
|
||||
@@ -314,11 +317,13 @@ wme_enabled=1
|
||||
ht_capab=[HT40+][SHORT-GI-40]
|
||||
```
|
||||
###### 5.Running the new Wireless AP
|
||||
$sudo systemctl reboot
|
||||
sudo systemctl reboot
|
||||
|
||||
### Install Apache2
|
||||
sudo apt install apache2
|
||||
|
||||
### Set web site
|
||||
$sudo vim ./sites-available/000-default.conf
|
||||
### Deploy web site
|
||||
sudo vim /etc/apache2/sites-available/000-default.conf
|
||||
```
|
||||
<VirtualHost *:8080> #80------>8080
|
||||
# The ServerName directive sets the request scheme, hostname and port that
|
||||
@@ -358,3 +363,27 @@ $sudo vim ./sites-available/000-default.conf
|
||||
|
||||
##### raspberry website document:
|
||||
> https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
|
||||
|
||||
# ChangeLog
|
||||
[2022.12.28]
|
||||
change meta_project_info to project_metas
|
||||
change project_report to project_reports
|
||||
alter table project_meta column cycle type string to jsonb
|
||||
|
||||
[2022.11.16]
|
||||
add python package SQLAlchemy
|
||||
add new column project(int4) in postgresSQL table recording_meta_datas
|
||||
add new postgresSQL table project_report
|
||||
add new postgresSQL table meta_project_info
|
||||
|
||||
[2022.10.18]
|
||||
socektTimeout from 1s -> 5s
|
||||
socketListen from 3 -> 20
|
||||
|
||||
[2022.09.30]
|
||||
add new column cycle(jsonb) in postgresSQL table projects
|
||||
|
||||
[2022.9.28]
|
||||
add python package numpy
|
||||
|
||||
|
||||
|
||||
@@ -1585,6 +1585,15 @@ class ControlAPI(metaclass=Router):
|
||||
|
||||
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
|
||||
class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)):
|
||||
|
||||
+16
-3
@@ -87,7 +87,8 @@ class DataAPI(metaclass=abc.ABCMeta):
|
||||
def update_device_configuration(self,
|
||||
device: Union[int, Device],
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
"""set device configuration.
|
||||
|
||||
:param device: device ID
|
||||
@@ -130,6 +131,14 @@ class DataAPI(metaclass=abc.ABCMeta):
|
||||
def hardware_test(self) -> JSON_OBJECT:
|
||||
""""""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def show_data(self, device: Union[int, Device]):
|
||||
"""show device data
|
||||
|
||||
:param device: device ID
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
@@ -146,7 +155,8 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
def update_device_configuration(self,
|
||||
device: Union[int, Device],
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
|
||||
# meta file
|
||||
if isinstance(meta_file, str):
|
||||
@@ -178,7 +188,7 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
raise TypeError('not a data decode format : ' + data_format.__class__.__name__)
|
||||
|
||||
# send
|
||||
self.send_command('update_device_configuration', device, meta_file, data_format)
|
||||
self.send_command('update_device_configuration', device, meta_file, data_format, project_info)
|
||||
|
||||
def is_sync(self, device: Union[None, int, Device] = None) -> bool:
|
||||
if isinstance(device, Device):
|
||||
@@ -191,6 +201,9 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
|
||||
def stop_sync(self, *device: Union[int, Device]):
|
||||
self.send_command('stop_sync', *self._to_device_id(*device))
|
||||
|
||||
def show_data(self, device: int):
|
||||
self.send_command('show_data', device)
|
||||
|
||||
@staticmethod
|
||||
def _to_device_id(*device: Union[int, Device]) -> Tuple[int, ...]:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from sqlalchemy import create_engine
|
||||
# from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "postgresql://biopro:BioProControlBox@127.0.0.1:5432/postgres"
|
||||
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URL)
|
||||
Session = sessionmaker(bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
@@ -0,0 +1,60 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from biopro.db.base import Session
|
||||
|
||||
from .base import Base
|
||||
|
||||
class Collection(Base):
|
||||
__tablename__ = "collections"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(255))
|
||||
parent = Column(JSONB)
|
||||
controller_id = Column(Integer)
|
||||
type = Column(String(255))
|
||||
description = Column(String(255))
|
||||
deleted = Column(Boolean)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
@classmethod
|
||||
def create_collection(cls, collection_name, parent):
|
||||
with Session() as session:
|
||||
name = cls.check_name_duplicate(collection_name, parent, 0)
|
||||
collection = Collection(
|
||||
name = name,
|
||||
parent = parent,
|
||||
type= "folder",
|
||||
)
|
||||
session.add(collection)
|
||||
session.commit()
|
||||
print('a', collection.id)
|
||||
return collection
|
||||
|
||||
@classmethod
|
||||
def check_name_duplicate(cls, collection_name, parent, n):
|
||||
with Session() as session:
|
||||
result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
|
||||
if result is None:
|
||||
return cls.generate_name(collection_name, n)
|
||||
else:
|
||||
new_num = n + 1
|
||||
# new_name = f"{collection_name}({new_num})"
|
||||
return cls.check_name_duplicate(collection_name, parent, new_num)
|
||||
|
||||
@classmethod
|
||||
def generate_name(cls, collection_name, n):
|
||||
if n==0:
|
||||
return collection_name
|
||||
else:
|
||||
return f"{collection_name}({n})"
|
||||
|
||||
@classmethod
|
||||
def find_collection(cls, collection_name, parent):
|
||||
with Session() as session:
|
||||
result = session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
|
||||
return result
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric, Float, BINARY, LargeBinary
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base, Session
|
||||
|
||||
class Device(Base):
|
||||
__tablename__ = "devices"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(255))
|
||||
mac_address = Column(String(255))
|
||||
serial_number = Column(String(255))
|
||||
configuration = Column(JSONB)
|
||||
library = Column(String(255))
|
||||
library_version = Column(String(255))
|
||||
device_version = Column(String(255))
|
||||
type = Column(String(255))
|
||||
battery = Column(Integer)
|
||||
temperature = Column(Float)
|
||||
auto_connect = Column(Boolean)
|
||||
connect_priority = Column(Integer)
|
||||
connect_time = Column(BigInteger)
|
||||
parameter_set = Column(JSONB)
|
||||
running = Column(Boolean)
|
||||
calibration = Column(LargeBinary)
|
||||
calibration_version = Column(Integer, default=-1)
|
||||
user_auth = Column(JSONB)
|
||||
deleted = Column(Boolean)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
@classmethod
|
||||
def update_device(cls, device, options):
|
||||
with Session() as session:
|
||||
result = session.query(Device).filter(Device.mac_address == device['mac_address']).first()
|
||||
for key, value in options.items():
|
||||
setattr(result, key, value)
|
||||
session.commit()
|
||||
|
||||
@classmethod
|
||||
def get_device(cls, device):
|
||||
with Session() as session:
|
||||
result = session.query(Device).filter(Device.mac_address == device['mac_address']).first()
|
||||
return result
|
||||
|
||||
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -0,0 +1,24 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base
|
||||
|
||||
class Project(Base):
|
||||
__tablename__ = "project"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
desc = Column(String)
|
||||
task = Column(JSONB)
|
||||
cycle = Column(JSONB)
|
||||
device = Column(JSONB)
|
||||
uuid = Column(String(36))
|
||||
user_auth = Column(JSONB)
|
||||
deleted = Column(Boolean, default = False)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -0,0 +1,29 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base, Session
|
||||
|
||||
class MetaProjectInfo(Base):
|
||||
__tablename__ = "project_metas"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
project = Column(String(36))
|
||||
cycle = Column(JSONB)
|
||||
task = Column(JSONB)
|
||||
serial_number = Column(Integer)
|
||||
deleted = Column(Boolean, default = False)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
@classmethod
|
||||
def create_project_meta(cls, project):
|
||||
with Session() as session:
|
||||
project_meta = MetaProjectInfo(project = project['project'], cycle= project['cycle'], task=project['task'], serial_number=int(project['serial_number']))
|
||||
session.add(project_meta)
|
||||
session.commit()
|
||||
return project_meta.id
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -0,0 +1,24 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base
|
||||
|
||||
class ProjectReport(Base):
|
||||
__tablename__ = "project_reports"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
desc = Column(String)
|
||||
task = Column(JSONB)
|
||||
cycle = Column(JSONB)
|
||||
device = Column(JSONB)
|
||||
uuid = Column(String(36))
|
||||
user_auth = Column(JSONB)
|
||||
deleted = Column(Boolean, default = False)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -350,6 +350,7 @@ class CC2650Device(Device):
|
||||
self._recording_file_name: str = 'recording_data'
|
||||
self._coeff: bytes = b''
|
||||
self._device_version = ""
|
||||
self._cali_version = -1
|
||||
|
||||
@property
|
||||
def device_id(self) -> int:
|
||||
@@ -428,17 +429,20 @@ class CC2650Device(Device):
|
||||
self._start_flag = False
|
||||
|
||||
def _encode_instruction(self, ins_type: int, ins_oper: int, *instruction: int) -> bytes:
|
||||
# print('_encode_instruction', ins_type, ins_oper, instruction)
|
||||
length = len(instruction)
|
||||
if length == 1 and instruction[0] < 0:
|
||||
return struct.pack('2B1b',
|
||||
(ins_type & 0xF0) | (self.device_id & 0x0F),
|
||||
(ins_oper & 0xF0) | (length & 0x0F),
|
||||
*instruction)
|
||||
|
||||
return struct.pack('%dB' % (length + 2),
|
||||
(ins_type & 0xF0) | (self.device_id & 0x0F),
|
||||
(ins_oper & 0xF0) | (length & 0x0F),
|
||||
(ins_oper & 0xFF),
|
||||
*instruction)
|
||||
if ins_type == None:
|
||||
return struct.pack('%dB' % length, *instruction)
|
||||
else:
|
||||
return struct.pack('%dB' % (length + 2),
|
||||
(ins_type & 0xF0) | (self.device_id & 0x0F),
|
||||
(ins_oper & 0xFF),
|
||||
*instruction)
|
||||
|
||||
def _decode_data(self, ins_oper: int, data: bytes) -> bytes:
|
||||
"""CIS data decoder.
|
||||
@@ -477,22 +481,24 @@ class CC2650Device(Device):
|
||||
|
||||
else:
|
||||
if data is not None and len(data) > 0:
|
||||
year = struct.unpack('<B', data[0:1])[0]
|
||||
month = struct.unpack('<B', data[1:2])[0]
|
||||
day = struct.unpack('<B', data[2:3])[0]
|
||||
hour = struct.unpack('<B', data[3:4])[0]
|
||||
minute = struct.unpack('<B', data[4:5])[0]
|
||||
mac1 = struct.unpack('<B', data[5:6])[0]
|
||||
mac2 = struct.unpack('<B', data[6:7])[0]
|
||||
mac1 = "%02X" % mac1
|
||||
mac2 = "%02X" % mac2
|
||||
year = struct.unpack('<B', data[2:3])[0]
|
||||
month = struct.unpack('<B', data[3:4])[0]
|
||||
day = struct.unpack('<B', data[4:5])[0]
|
||||
hour = struct.unpack('<B', data[5:6])[0]
|
||||
minute = struct.unpack('<B', data[6:7])[0]
|
||||
# mac1 = struct.unpack('<B', data[7:8])[0]
|
||||
# mac2 = struct.unpack('<B', data[8:9])[0]
|
||||
# mac1 = "%02X" % mac1
|
||||
# mac2 = "%02X" % mac2
|
||||
|
||||
self._device_version = str(year) + '/' + str(month) + '/' + str(day) + " " + str(hour) + ":" + str(
|
||||
minute) + " | " + str(mac1) + ":" + str(mac2)
|
||||
minute)
|
||||
# + " | " + str(mac1) + ":" + str(mac2)
|
||||
|
||||
@property
|
||||
def battery(self) -> int:
|
||||
self.update_battery_info()
|
||||
if self._start_flag == False:
|
||||
self.update_battery_info()
|
||||
return self._battery
|
||||
|
||||
@property
|
||||
@@ -537,7 +543,7 @@ class CC2650Device(Device):
|
||||
|
||||
else:
|
||||
if data is not None and len(data) > 2 :
|
||||
battery = struct.unpack('<H', data[1:3])[0]
|
||||
battery = struct.unpack('<H', data[2:4])[0]
|
||||
if battery is not None:
|
||||
self._battery = battery
|
||||
|
||||
@@ -549,6 +555,39 @@ class CC2650Device(Device):
|
||||
self.update_calibration_info(device_type)
|
||||
|
||||
return self._coeff
|
||||
|
||||
def _check_crc(self, data):
|
||||
data_chk_sum = data[-1]
|
||||
|
||||
# print('data:', list(data), 'data_chk_sum:', data_chk_sum)
|
||||
# print('data[0:-1]:', list(data[0:-1]), 'check_sum:', sum(data[0:-1]) & 0b11111111)
|
||||
|
||||
if data_chk_sum == sum(data[0:-1]) & 0b11111111:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def update_cali_version(self) -> bool:
|
||||
for _ in range(5):
|
||||
try:
|
||||
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, 0)
|
||||
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
|
||||
except SendInstructionTimeoutError:
|
||||
self._master.log_warn('device', self.device_id, 'update cali version error')
|
||||
return False
|
||||
except RuntimeError:
|
||||
self._master.log_warn('device', self.device_id, 'update cali version error')
|
||||
return False
|
||||
else:
|
||||
version = self._master.read_characteristic(self.device_id,CC2650MasterDevice.RETURN_HANDLE)
|
||||
|
||||
if self._check_crc(version):
|
||||
self._cali_version = struct.unpack('<H', version[2:4])[0]
|
||||
print('self._cali_version=', self._cali_version)
|
||||
return True
|
||||
|
||||
self._master.log_warn('device', self.device_id, 'update cali version error')
|
||||
return False
|
||||
|
||||
def update_calibration_info(self, device_type: str):
|
||||
""" get device calibration info """
|
||||
@@ -571,20 +610,6 @@ class CC2650Device(Device):
|
||||
elif device_type == 'TDC4VC':
|
||||
i = 0
|
||||
request_times = 0
|
||||
# neulive 2.1 (only support ch1~ch8)
|
||||
# try:
|
||||
# # send
|
||||
# code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, 0)
|
||||
# self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
|
||||
# # receive
|
||||
# data = self._master.read_characteristic(self.device_id, CC2650MasterDevice.RETURN_HANDLE)
|
||||
#
|
||||
# coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
|
||||
# except SendInstructionTimeoutError:
|
||||
# self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
|
||||
# except RuntimeError:
|
||||
# self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
|
||||
|
||||
while i < 4:
|
||||
try:
|
||||
# print('i', i)
|
||||
@@ -660,43 +685,34 @@ class CC2650Device(Device):
|
||||
break
|
||||
|
||||
elif device_type == 'EISZeroOne':
|
||||
i = 0
|
||||
request_times = 0
|
||||
while i < 7:
|
||||
try:
|
||||
# send
|
||||
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
|
||||
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
|
||||
i = 1
|
||||
while i <= 24:
|
||||
for _ in range(5):
|
||||
try:
|
||||
# send
|
||||
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
|
||||
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
|
||||
|
||||
sleep(0.1)
|
||||
|
||||
# receive
|
||||
data = self._master.read_characteristic(self.device_id,
|
||||
CC2650MasterDevice.RETURN_HANDLE)
|
||||
coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
|
||||
|
||||
except SendInstructionTimeoutError as e:
|
||||
print(e)
|
||||
self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
|
||||
raise BaseException
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
self._master.log_warn('device', self.device_id, 'update_calibration_info no response - 2')
|
||||
request_times += 1
|
||||
if request_times > 3:
|
||||
self._master.reset(self.device_id)
|
||||
break
|
||||
else:
|
||||
# print('data success')
|
||||
if len(data) > 0:
|
||||
i += 1
|
||||
except SerialTimeoutException:
|
||||
self._master.log_warn('device', self.device_id, 'send update_calibration_info instruction fail')
|
||||
continue
|
||||
|
||||
else:
|
||||
request_times += 1
|
||||
if request_times > 3:
|
||||
self._master.reset(self.device_id)
|
||||
break
|
||||
|
||||
try:
|
||||
# receive
|
||||
data = self._master.read_characteristic(self.device_id,
|
||||
CC2650MasterDevice.RETURN_HANDLE)
|
||||
except RecvTimeout:
|
||||
self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
|
||||
|
||||
else:
|
||||
if self._check_crc(data) and data is not None:
|
||||
coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
|
||||
i += 1
|
||||
else:
|
||||
self._master.log_warn('device', self.device_id, 'update_calibration_info crc wrong')
|
||||
continue
|
||||
|
||||
else:
|
||||
# default: neulive 2.1
|
||||
for i in range(1):
|
||||
@@ -1950,120 +1966,6 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
"""initialize cc2650 (master)"""
|
||||
pass
|
||||
|
||||
def scan_send_ins(self):
|
||||
# send scan command
|
||||
try:
|
||||
print(':: scan_send_ins ::', self.CC2650_COMMAND_LEN, 3, 0, 0)
|
||||
self._cc2650.send(self.CC2650_COMMAND_LEN, 3, 0, 0)
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('send scan fail') from e
|
||||
|
||||
else:
|
||||
# wait scanning
|
||||
# sleep(2)
|
||||
clean_buf = self._cc2650.receive_timeout("20B", timeout=3)
|
||||
print("clean_buf = ", clean_buf)
|
||||
|
||||
# def cc2650_uart_irq(self):
|
||||
# uart_irq = self.get_uart_irq_pin()
|
||||
# uart_irq.output(False)
|
||||
# sleep(0.001)
|
||||
# uart_irq.output(True)
|
||||
|
||||
@synchronized
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
self._found = found = []
|
||||
self._found_with_id = []
|
||||
hdr_BPHS = [66, 80, 72, 83]
|
||||
scan_response: Union[Optional[tuple], Any] = None
|
||||
|
||||
# build scan instruction
|
||||
scan_ins = bytearray()
|
||||
scan_ins.append(3) #scan instruction
|
||||
scan_ins.append(1) #length
|
||||
scan_ins.append(0xF1)
|
||||
|
||||
# print('send_scan', bytes(scan_ins))
|
||||
self._cc2650.send("bytes", bytes(scan_ins))
|
||||
|
||||
try:
|
||||
scan_response = self._cc2650.recv_uart(timeout)
|
||||
except RecvTimeout:
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# self._interface.flush()
|
||||
return False
|
||||
|
||||
# instruction format:
|
||||
# ins[0]: get_scan_response = 0x04
|
||||
# ins[1]: number of scanned device=0; a certain device = device_id (could be 1~8)
|
||||
# ins[2]: addr=MAC=1, localName=2, company_code=3, version_info=4, battery_info=5, all_info=6;
|
||||
# attr_length=0, e.g. len(addr)=6, len(company_code)=4
|
||||
local_mac = None
|
||||
local_cc = None
|
||||
local_ver = None
|
||||
local_bat = None
|
||||
local_name = None
|
||||
|
||||
local_addr_type = None
|
||||
|
||||
# get device attribute length
|
||||
attr_length = [6, 4, 6, 5, 20]
|
||||
index = 0
|
||||
|
||||
local_mac = get_device_mac_in_address_format(scan_response[index:index + 6])
|
||||
index = index + 6
|
||||
# print("local_mac = ", hex(local_mac[0]), hex(local_mac[1]),
|
||||
# hex(local_mac[2]), hex(local_mac[3]),
|
||||
# hex(local_mac[4]), hex(local_mac[5]))
|
||||
|
||||
local_cc = get_device_company_code(scan_response[index:index + 4])
|
||||
index = index + 4
|
||||
# print("local_cc = ", local_cc)
|
||||
|
||||
local_ver = scan_response[index:index + 6]
|
||||
index = index + 6
|
||||
# print("local_ver = ", local_ver)
|
||||
|
||||
local_bat = get_device_battery_info(scan_response[index:index + 5])
|
||||
index = index + 5
|
||||
# print("local_bat = ", local_bat)
|
||||
|
||||
local_name = get_device_name_in_string_format(list(scan_response[index:index + 20]))
|
||||
index = index + 20
|
||||
# print("local_name = ", local_name)
|
||||
|
||||
# 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 = 0xFF
|
||||
index = index + 1
|
||||
# print("local_addr_type = ", local_addr_type)
|
||||
|
||||
response = is_headstage_device_central_version(local_mac,
|
||||
local_addr_type,
|
||||
local_name,
|
||||
local_cc,
|
||||
local_ver,
|
||||
local_bat)
|
||||
if response is not None:
|
||||
self.log_info('found', address_str(response.mac_address), response.serial_number)
|
||||
self._interface.flush_input()
|
||||
|
||||
# apppend into db
|
||||
devicesList = DeviceAPI.getByMac(address_str(response.mac_address))
|
||||
if devicesList is not None:
|
||||
if len(devicesList) == 0:
|
||||
DeviceAPI.create(response.device_name, local_ver, address_str(response.mac_address))
|
||||
|
||||
found.append(response)
|
||||
# print('scan_done_found', found)
|
||||
self._found_with_id.append((response, 0 + 1))
|
||||
callback(response)
|
||||
|
||||
return True
|
||||
|
||||
def decode_uart_preamble(self, raw_uart: tuple, expect_ret_len: int = 0) -> Optional[list]:
|
||||
# print("decode_uart_preamble: raw_uart = ", raw_uart)
|
||||
if raw_uart is None:
|
||||
@@ -2090,34 +1992,154 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
return self._found
|
||||
|
||||
def check_mem_survive(self) -> Optional[CC2650Device]:
|
||||
ack = []
|
||||
chk_mem_response = None
|
||||
ins = bytearray()
|
||||
ins.append(10)
|
||||
ins.append(1) #length
|
||||
|
||||
ins.append(0x0A)
|
||||
ins.append(0x01) #length
|
||||
ins.append(0xF1)
|
||||
# print('ins', list(ins))
|
||||
self._interface.flush_input()
|
||||
|
||||
try:
|
||||
self.log_verbose('[CC2650]', 'check_mem_survive att_write','0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('device CC2650 check_mem_survive timeout') from e
|
||||
except SerialTimeoutException:
|
||||
self.log_verbose('[CC2650]', 'check_mem_survive send fail')
|
||||
|
||||
else:
|
||||
try:
|
||||
ack = self._cc2650.recv_uart(0.001)
|
||||
chk_mem_response = self._cc2650.recv_uart(0.001)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_info("no memory board")
|
||||
self.log_verbose('[CC2650]', 'check_mem_survive response timeout, no memory board')
|
||||
|
||||
# else:
|
||||
# print('ack=', ack)
|
||||
if chk_mem_response is None:
|
||||
return False
|
||||
|
||||
if ack == [3]:
|
||||
pack_len = chk_mem_response[0]
|
||||
mem_ack = chk_mem_response[1:pack_len+1]
|
||||
|
||||
if mem_ack == [3]:
|
||||
chk_mem_response_hex = ''.join(format(i, '02X') for i in chk_mem_response)
|
||||
self.log_verbose('[CC2650]', 'check_mem_survive success', '0x'+chk_mem_response_hex)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@synchronized
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
self._found = found = []
|
||||
self._found_with_id = []
|
||||
scan_response = None
|
||||
ins = bytearray()
|
||||
|
||||
ins.append(0x03)
|
||||
ins.append(0x01) #length
|
||||
ins.append(0xF1)
|
||||
self._interface.flush_input()
|
||||
|
||||
for _ in range(5):
|
||||
try:
|
||||
self.log_verbose('[CC2650]', 'scan_callback att_write','0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except SerialTimeoutException:
|
||||
self.log_verbose('[CC2650]', 'scan_callback send fail, rescan')
|
||||
continue
|
||||
|
||||
else:
|
||||
try:
|
||||
scan_response = self._cc2650.recv_uart(0.01)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_verbose('[CC2650]', 'scan_callback response timeout, no device, rescan')
|
||||
continue
|
||||
|
||||
else:
|
||||
if scan_response is None:
|
||||
self.log_verbose('[CC2650]', 'scan_callback response is None, rescan')
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
if scan_response is None:
|
||||
self.log_verbose('[CC2650]', 'scan_callback response is None--2')
|
||||
return False
|
||||
|
||||
scan_response_hex = ''.join(format(i, '02X') for i in scan_response)
|
||||
self.log_verbose('[CC2650]', 'scan_callback success', '0x'+scan_response_hex)
|
||||
|
||||
if len(scan_response) <= 2:
|
||||
print('******************************************************************')
|
||||
print('******************************************************************')
|
||||
print('******************************************************************')
|
||||
print('******************************************************************')
|
||||
print('****need to fix, len(scan) <= 2')
|
||||
print()
|
||||
return False
|
||||
|
||||
pack_len = scan_response[0]
|
||||
device_info_pkg = scan_response[1:pack_len+1]
|
||||
|
||||
# instruction format:
|
||||
# ins[0]: get_scan_response = 0x04
|
||||
# ins[1]: number of scanned device=0; a certain device = device_id (could be 1~8)
|
||||
# ins[2]: addr=MAC=1, localName=2, company_code=3, version_info=4, battery_info=5, all_info=6;
|
||||
# attr_length=0, e.g. len(addr)=6, len(company_code)=4
|
||||
local_mac = None
|
||||
local_cc = None
|
||||
local_ver = None
|
||||
local_bat = None
|
||||
local_name = None
|
||||
local_addr_type = None
|
||||
|
||||
# get device attribute length
|
||||
attr_length = [6, 4, 6, 5, 20]
|
||||
index = 0
|
||||
|
||||
local_mac = get_device_mac_in_address_format(device_info_pkg[index:index + 6])
|
||||
index = index + 6
|
||||
|
||||
local_cc = get_device_company_code(device_info_pkg[index:index + 4])
|
||||
index = index + 4
|
||||
|
||||
local_ver = device_info_pkg[index:index + 6]
|
||||
index = index + 6
|
||||
|
||||
local_bat = get_device_battery_info(device_info_pkg[index:index + 5])
|
||||
index = index + 5
|
||||
|
||||
local_name = get_device_name_in_string_format(list(device_info_pkg[index:index + 20]))
|
||||
index = index + 20
|
||||
|
||||
local_addr_type = int(device_info_pkg[index:index + 1][0])
|
||||
|
||||
index = index + 1
|
||||
|
||||
response = is_headstage_device_central_version(local_mac,
|
||||
local_addr_type,
|
||||
local_name,
|
||||
local_cc,
|
||||
local_ver,
|
||||
local_bat)
|
||||
if response is not None:
|
||||
self.log_info('found', address_str(response.mac_address), response.serial_number)
|
||||
self._interface.flush_input()
|
||||
|
||||
# apppend into db
|
||||
devicesList = DeviceAPI.getByMac(address_str(response.mac_address))
|
||||
if devicesList is not None:
|
||||
if len(devicesList) == 0:
|
||||
DeviceAPI.create(response.device_name, local_ver, address_str(response.mac_address))
|
||||
|
||||
found.append(response)
|
||||
# print('scan_done_found', found)
|
||||
self._found_with_id.append((response, 0 + 1))
|
||||
callback(response)
|
||||
|
||||
return True
|
||||
|
||||
@synchronized
|
||||
def connect(self, response: DeviceResponseInfo, direct_connect: bool = False) -> Optional[CC2650Device]:
|
||||
if self._handle is not None:
|
||||
@@ -2127,225 +2149,202 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
addr_type = response.addr_type
|
||||
address_s = cc2650.address_str(address)
|
||||
|
||||
self.log_info(DEVICE_CONNECTING, address_s)
|
||||
|
||||
connect_ins = bytearray()
|
||||
connect_ins.append(5)
|
||||
connect_ins.append(8) #length
|
||||
connect_ins.append(addr_type)
|
||||
connect_ins.append(address[0])
|
||||
connect_ins.append(address[1])
|
||||
connect_ins.append(address[2])
|
||||
connect_ins.append(address[3])
|
||||
connect_ins.append(address[4])
|
||||
connect_ins.append(address[5])
|
||||
connect_ins.append(0xF1)
|
||||
|
||||
connected = False
|
||||
connect_response = None
|
||||
ins = bytearray()
|
||||
|
||||
# send connect command
|
||||
if direct_connect is True:
|
||||
|
||||
# send device mac and addrType
|
||||
try:
|
||||
self._cc2650.send("bytes", bytes(connect_ins))
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('device CC2650 connect fail') from e
|
||||
return None
|
||||
|
||||
# connection establish done?
|
||||
for retry_recv_ack in range(10):
|
||||
try:
|
||||
con_done = self._cc2650.recv_uart(timeout = 0.5)
|
||||
# print("con_done = ", con_done)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_info("recv connection timeout, retry... ")
|
||||
continue
|
||||
|
||||
# is the ack valid?
|
||||
if con_done is None:
|
||||
continue
|
||||
|
||||
elif con_done[0] is 46 and \
|
||||
con_done[1] is 80 and \
|
||||
con_done[2] is 48 and \
|
||||
con_done[3] is 4:
|
||||
connected = True
|
||||
break
|
||||
else:
|
||||
for dev in self._found:
|
||||
if dev.mac_address == address:
|
||||
|
||||
# send device mac and addrType
|
||||
try:
|
||||
# print('send_connect',bytes(connect_ins))
|
||||
self._cc2650.send("bytes", bytes(connect_ins))
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('device CC2650 connect fail') from e
|
||||
|
||||
else:
|
||||
sleep(2)
|
||||
|
||||
# connection establish done?
|
||||
for retry_recv_ack in range(5):
|
||||
self._cc2650.send("bytes", bytes((0, 0, 0, 0)))
|
||||
|
||||
try:
|
||||
con_done = self._cc2650.recv_uart(timeout = 0.1)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_info("recv connection timeout, retry... ")
|
||||
continue
|
||||
|
||||
# is the ack valid?
|
||||
if con_done is None:
|
||||
continue
|
||||
|
||||
elif con_done[0] is 46 and \
|
||||
con_done[1] is 80 and \
|
||||
con_done[2] is 48 and \
|
||||
con_done[3] is 4:
|
||||
connected = True
|
||||
# print('con_done=', con_done)
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
# if select device is invalid or connect failed
|
||||
ins.append(0x05)
|
||||
ins.append(0x08) #length
|
||||
ins.append(addr_type)
|
||||
ins.append(address[0])
|
||||
ins.append(address[1])
|
||||
ins.append(address[2])
|
||||
ins.append(address[3])
|
||||
ins.append(address[4])
|
||||
ins.append(address[5])
|
||||
ins.append(0xF1)
|
||||
self._interface.flush_input()
|
||||
if connected is False:
|
||||
if direct_connect is True:
|
||||
self.reset_internal()
|
||||
self.reset_hardware()
|
||||
self._interface.flush()
|
||||
return None
|
||||
|
||||
# CC2650Device(device_id, master, scan_response) is a slave device
|
||||
# device_id is don't care, because it will be overwrite later
|
||||
dont_care = 0
|
||||
self._device = ret = CC2650Device(device_id=dont_care, master=self, response_info=response)
|
||||
self.log_info(DEVICE_CONNECTED, address_s)
|
||||
sleep(0.5)
|
||||
print('ret',ret)
|
||||
for retry in range(5):
|
||||
try:
|
||||
self.log_verbose('[CC2650]', 'connect att_write', '0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
return ret
|
||||
except RecvTimeout:
|
||||
self.log_verbose('[CC2650]', 'connect send fail')
|
||||
continue
|
||||
|
||||
else:
|
||||
try:
|
||||
connect_response = self._cc2650.recv_uart(2)
|
||||
except RecvTimeout:
|
||||
# self.log_verbose('[CC2650]', 'connect response timeout')
|
||||
if retry < 5:
|
||||
self.log_verbose('[CC2650]', 'connect retry')
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
if connect_response is None:
|
||||
self.log_verbose('[CC2650]', 'connect response timeout')
|
||||
return False
|
||||
|
||||
pack_len = connect_response[0]
|
||||
connect_ack = connect_response[1:pack_len+1]
|
||||
if pack_len == 1:
|
||||
if connect_ack[0] == 3:
|
||||
connected = True
|
||||
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
|
||||
self.log_verbose('[CC2650]', 'connect success', '0x'+connect_response_hex)
|
||||
|
||||
elif pack_len == 4:
|
||||
if connect_ack[0] == 46 and connect_ack[1] == 80 and \
|
||||
connect_ack[2] == 48 and connect_ack[3] == 4:
|
||||
connected = True
|
||||
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
|
||||
self.log_verbose('[CC2650]', 'connect success', '0x'+connect_response_hex)
|
||||
|
||||
if connected == True:
|
||||
# CC2650Device(device_id, master, scan_response) is a slave device
|
||||
# device_id is don't care, because it will be overwrite later
|
||||
dont_care = 0
|
||||
self._device = ret = CC2650Device(device_id=dont_care, master=self, response_info=response)
|
||||
self.log_verbose('[CC2650]', DEVICE_CONNECTED, address_s)
|
||||
return ret
|
||||
|
||||
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
|
||||
self.log_verbose('[CC2650]', 'connect fail', '0x'+connect_response_hex)
|
||||
return False
|
||||
|
||||
@synchronized
|
||||
def disconnect(self, device: int, force=False) -> bool:
|
||||
self.log_info(DEVICE_DISCONNECTING, device)
|
||||
|
||||
ins = bytearray()
|
||||
ins.append(8)
|
||||
ins.append(1) #length
|
||||
|
||||
ins.append(0x08)
|
||||
ins.append(0x01) #length
|
||||
ins.append(0xF1)
|
||||
self._interface.flush_input()
|
||||
|
||||
for retry in range(5):
|
||||
try:
|
||||
self.log_verbose('[CC2650]', 'disconnect att_write','0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except SerialTimeoutException:
|
||||
self.log_verbose('[CC2650]', 'disconnect send fail')
|
||||
continue
|
||||
|
||||
else:
|
||||
self.reset_internal()
|
||||
self.reset_hardware()
|
||||
self.log_verbose('[CC2650]', 'disconnect success')
|
||||
return True
|
||||
# try:
|
||||
# disconnect_response = self._cc2650.recv_uart(0.01)
|
||||
# print(disconnect_response)
|
||||
|
||||
# except RecvTimeout:
|
||||
# self.log_verbose('[CC2650]', 'disconnect response timeout')
|
||||
# if retry < 5:
|
||||
# self.log_verbose('[CC2650]', 'connect retry')
|
||||
# continue
|
||||
# else:
|
||||
# break
|
||||
|
||||
# if disconnect_response is None:
|
||||
# return False
|
||||
|
||||
# pack_len = disconnect_response[0]
|
||||
# disconnect_ack = disconnect_response[1:pack_len+1]
|
||||
|
||||
# if disconnect_ack == [3]:
|
||||
# disconnect_response_hex = ''.join(format(i, '02X') for i in disconnect_response)
|
||||
# self.log_verbose('[CC2650]', 'disconnect success', '0x'+disconnect_response_hex)
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# return True
|
||||
|
||||
self.log_verbose('[CC2650]', 'disconnect fail')
|
||||
return False
|
||||
|
||||
@synchronized
|
||||
def write_characteristic(self, device: int, handle: int, data: bytes) -> bool:
|
||||
write_response = None
|
||||
ins = bytearray()
|
||||
|
||||
ins.append(0x06)
|
||||
if len(data) + 2 > 255:
|
||||
ins.append(255)
|
||||
else:
|
||||
ins.append(len(data)+2) #length = handle + C0C0XXXX(data len) + F1
|
||||
ins.append(handle)
|
||||
ins.extend(data)
|
||||
ins.append(0xF1)
|
||||
self._interface.flush_input()
|
||||
|
||||
try:
|
||||
# print('send_disconnect',bytes(ins))
|
||||
self.log_verbose('[CC2650]', 'write_characteristic', device, str(hex(handle).upper()))
|
||||
self.log_verbose('[CC2650]', 'write_characteristic att_write','0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_warn('disconnect time out')
|
||||
return False
|
||||
|
||||
except RuntimeError as e:
|
||||
self.log_warn('suppressed error', str(e))
|
||||
return False
|
||||
|
||||
except SerialTimeoutException:
|
||||
self.log_verbose('[CC2650]', 'write_characteristic send fail')
|
||||
|
||||
else:
|
||||
sleep(0.01)
|
||||
try:
|
||||
write_response = self._cc2650.recv_uart(0.5)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_verbose('[CC2650]', 'write_characteristic response timeout')
|
||||
|
||||
if write_response is None:
|
||||
self.log_verbose('[CC2650]', 'write_characteristic fail')
|
||||
return False
|
||||
|
||||
pack_len = write_response[0]
|
||||
write_ack = write_response[1:pack_len+1]
|
||||
|
||||
if write_ack == [3]:
|
||||
write_response_hex = ''.join(format(i, '02X') for i in write_response)
|
||||
self.log_verbose('[CC2650]', 'write_characteristic success', '0x'+write_response_hex)
|
||||
return True
|
||||
|
||||
finally:
|
||||
self.log_info(DEVICE_DISCONNECTED, device)
|
||||
|
||||
# reset single 2650 after disconnected
|
||||
self.reset_internal()
|
||||
self.reset_hardware()
|
||||
self._interface.flush()
|
||||
self.log_verbose('[CC2650]', 'write_characteristic fail')
|
||||
return False
|
||||
|
||||
@synchronized
|
||||
def read_characteristic(self, device: int, handle: int) -> Optional[bytes]:
|
||||
|
||||
# print("read_characteristic, expect_data_length = ", expect_data_length)
|
||||
|
||||
ret = None
|
||||
read_response = None
|
||||
ins = bytearray()
|
||||
ins.append(7)
|
||||
ins.append(2) #length
|
||||
|
||||
ins.append(0x07)
|
||||
ins.append(0x02) #length
|
||||
ins.append(handle)
|
||||
ins.append(0xF1)
|
||||
|
||||
for _ in range(2):
|
||||
try:
|
||||
# print('send_read',bytes(ins))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
except SerialTimeoutException:
|
||||
raise RecvTimeout('device CC2650 send read_characteristic fail')
|
||||
|
||||
try:
|
||||
ret = self._cc2650.recv_uart(timeout = 2)
|
||||
except Exception as e2:
|
||||
raise RecvTimeout()
|
||||
else:
|
||||
# print("======== read ret = ", ret)
|
||||
self._interface.flush_input()
|
||||
|
||||
# try:
|
||||
# ret = self._cc2650.recv_uart(timeout = 1)
|
||||
# except Exception as e2:
|
||||
# raise RecvTimeout()
|
||||
# else:
|
||||
# # print("read_characteristic ret = ", ret)
|
||||
# pass
|
||||
|
||||
if ret is None:
|
||||
return None
|
||||
|
||||
return bytes(ret)
|
||||
|
||||
@synchronized
|
||||
def write_characteristic(self, device: int, handle: int, data: bytes):
|
||||
|
||||
# print("device", device)
|
||||
# print("handle", handle)
|
||||
# print("data", data.hex())
|
||||
# self.log_info('reset')
|
||||
self.log_verbose('write_characteristic', device, handle)
|
||||
self.log_verbose('[CC2650]', 'att_write', str.upper(data.hex()))
|
||||
ack = None
|
||||
ret = None
|
||||
|
||||
data_array = bytearray()
|
||||
data_array.append(6)
|
||||
data_array.append(len(data)+2) #length
|
||||
data_array.append(handle)
|
||||
data_array.extend(data)
|
||||
data_array.append(0xF1)
|
||||
|
||||
self._interface.flush_input()
|
||||
|
||||
try:
|
||||
self._cc2650.send("bytes", bytes(data_array))
|
||||
# print('send_write',bytes(data_array))
|
||||
self.log_verbose('[CC2650]', 'read_characteristic', device, str(hex(handle).upper()))
|
||||
self.log_verbose('[CC2650]', 'read_characteristic att_write','0x'+str.upper(ins.hex()))
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('device CC2650 send instruction fail') from e
|
||||
|
||||
# read error code
|
||||
try:
|
||||
ret = self._cc2650.recv_uart()
|
||||
|
||||
# print("_______ write ack = ", ret)
|
||||
except Exception as e2:
|
||||
pass
|
||||
except SerialTimeoutException:
|
||||
self.log_verbose('[CC2650]', 'read_characteristic send fail')
|
||||
|
||||
else:
|
||||
pass
|
||||
try:
|
||||
read_response = self._cc2650.recv_uart(1)
|
||||
|
||||
self._interface.flush_input()
|
||||
self._interface.flush_output()
|
||||
except RecvTimeout:
|
||||
self.log_verbose('[CC2650]', 'read_characteristic response timeout')
|
||||
|
||||
if read_response is None:
|
||||
return None
|
||||
|
||||
read_response_hex = ''.join(format(i, '02X') for i in read_response)
|
||||
self.log_verbose('[CC2650]', 'read_characteristic success', '0x'+read_response_hex)
|
||||
|
||||
return bytes(read_response)
|
||||
|
||||
def set_notify(self, device: Union[int, Device], enable: bool):
|
||||
if isinstance(device, CompletedDevice):
|
||||
@@ -2446,7 +2445,6 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
self._cc2650_log_level = self.log_level
|
||||
|
||||
def read_characteristic(self, device: int, handle: int) -> Optional[bytes]:
|
||||
self.log_verbose('read_characteristic', device, '0x%02X' % handle)
|
||||
|
||||
master = self._cc2650[device]
|
||||
|
||||
@@ -2504,11 +2502,6 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
self._interface.flush()
|
||||
self._selector.select(device_id)
|
||||
# self._mem_selector.select(device_id)
|
||||
# print("multiMaster selector = ", device_id)
|
||||
# print("\n")
|
||||
|
||||
# device._notify_flag = enable
|
||||
try:
|
||||
master.write_characteristic(device_id, self.NOTIFY_HANDLE, value)
|
||||
except SendInstructionTimeoutError:
|
||||
|
||||
@@ -574,20 +574,23 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
:param device: device ID or response info
|
||||
:return: CompletedDevice, None if not found.
|
||||
"""
|
||||
if isinstance(device, int):
|
||||
for slave in self._device:
|
||||
if slave.device_id == device:
|
||||
return slave
|
||||
try:
|
||||
if isinstance(device, int):
|
||||
for slave in self._device:
|
||||
if slave.device_id == device:
|
||||
return slave
|
||||
|
||||
elif isinstance(device, str):
|
||||
for slave in self._device:
|
||||
if ':'.join('{:02x}'.format(b) for b in slave.mac_address) == device.lower():
|
||||
return slave
|
||||
elif isinstance(device, str):
|
||||
for slave in self._device:
|
||||
if ':'.join('{:02x}'.format(b) for b in slave.mac_address) == device.lower():
|
||||
return slave
|
||||
|
||||
elif isinstance(device, DeviceInfo):
|
||||
for slave in self._device:
|
||||
if device.match(slave):
|
||||
return slave
|
||||
elif isinstance(device, DeviceInfo):
|
||||
for slave in self._device:
|
||||
if device.match(slave):
|
||||
return slave
|
||||
except BaseException as e:
|
||||
self.log_error('device not found', str(device))
|
||||
|
||||
return None
|
||||
|
||||
@@ -829,6 +832,12 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
|
||||
elif func == InternalInstruction.PREDEFINED_DISABLE_CACHE:
|
||||
self._device_disable_cache(device, *para)
|
||||
|
||||
elif func == InternalInstruction.PREDEFINED_IDLE:
|
||||
self._idle(device, *para)
|
||||
|
||||
elif func == InternalInstruction.PREDEFINED_COUNTDOWN:
|
||||
self._countdown(device, *para)
|
||||
|
||||
elif isinstance(device, DebugDevice):
|
||||
if func == InternalInstruction.PREDEFINED_NOTIFY:
|
||||
@@ -848,6 +857,16 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
InternalInstruction.PREDEFINED_DATA_FORMAT,
|
||||
f)
|
||||
|
||||
def _idle(self, device: Device, expr: AnyStr):
|
||||
self._handler.device_internal_command(device.device_id,
|
||||
InternalInstruction.PREDEFINED_IDLE,
|
||||
None)
|
||||
|
||||
def _countdown(self, device: Device, expr: AnyStr):
|
||||
self._handler.device_internal_command(device.device_id,
|
||||
InternalInstruction.PREDEFINED_COUNTDOWN,
|
||||
expr)
|
||||
|
||||
def _device_data_format_cali(self, device: Device, expr: str, cali: bytes = None):
|
||||
if cali is None:
|
||||
cali = device.calibration_info(expr)
|
||||
|
||||
+388
-189
@@ -1,6 +1,7 @@
|
||||
import abc
|
||||
import struct
|
||||
import math
|
||||
import numpy
|
||||
from typing import Optional, TypeVar, Generic, Tuple, Dict, List, AnyStr
|
||||
from datetime import datetime
|
||||
|
||||
@@ -853,7 +854,8 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
|
||||
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
|
||||
'_total_time_stamp', '_mode', '_cycle_start_time',
|
||||
'_mode_stop')
|
||||
'_mode_stop', '_show_data',
|
||||
'_last_mem_wrong_information', '_last_mem_cnt', '_last_elite_notify_times')
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -868,6 +870,12 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
self._mode = 0
|
||||
self._cycle_start_time = []
|
||||
|
||||
self._show_data = False
|
||||
|
||||
self._last_mem_wrong_information = -1
|
||||
self._last_mem_cnt = -1
|
||||
self._last_elite_notify_times = -1
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.NAME
|
||||
@@ -881,23 +889,70 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
def decode(self, data: bytes) -> Optional[RecordingData]:
|
||||
if len(data) < 18:
|
||||
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
|
||||
ch2 = struct.unpack('<i', data[12:16])[0] # unit: uV
|
||||
impedance = struct.unpack('<i', data[16:20])[0] # unit: mOm
|
||||
if self._mode == 16:
|
||||
voltage = impedance - ch2
|
||||
else:
|
||||
voltage = ch2
|
||||
|
||||
#/* Elite Notify data:
|
||||
# * +--------+----------+---------+---------+---------+-----------+-----------------+
|
||||
# * | id(1B) | time(4B) | ch1(4B) | ch2(4B) | ch3(4B) | cycle(2B) | finish_flag(1B) |
|
||||
# * | bat(4B) | notify#(1B) | ch4(4B) | ch5(4B) | ch6(4B) | __(3B) |
|
||||
# * +---------+-------------+---------+---------+---------+--------+
|
||||
# */
|
||||
#/*
|
||||
# * EliteADCControl(): use ADC plot, and send what data to controller
|
||||
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
|
||||
# * | MODE | ch1 | ch2 | ch3 | cycle | ch4 |
|
||||
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
|
||||
# * | CURVE_IV | Iin | Vout | Vin | | Vmon |
|
||||
# * | CURVE_IV_CY | Iin | Vout | Vin | v | Vmon |
|
||||
# * | CURVE_VO | Iin | Vout | Vin | | Vmon |
|
||||
# * | CURVE_RT | Iin | Vout | R | | Vmon |
|
||||
# * | CURVE_VT | Iin | Vin | | | |
|
||||
# * | CURVE_IT | Iin | Vin | Vout | | Vmon |
|
||||
# * | CURVE_CC | Iin | Vin | Vout | | Vmon |
|
||||
# * | CURVE_CP | Iin | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_CV | Iin | Vout-Vin | Vout | v | Vmon |
|
||||
# * | CURVE_LSV | Iin | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_CA | Iin | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_OCP | Iin | Vmon-Vin | Vin | | Vmon |
|
||||
# * | CURVE_UNI_PULSE | pul1_Iin | pul2_Iin | | | |
|
||||
# * | CURVE_DPV | c1&c2_avg | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_DPV_SMPRATE | Iin | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_DPV_ADVANCE | c1&c2_avg | Vout-Vin | Vout | | Vmon |
|
||||
# * | CURVE_DPV_ADVANCE_SMPRATE | Iin | Vout-Vin | Vout | | Vmon |
|
||||
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
|
||||
# *
|
||||
# * ps. c1_avg = pul1_Iin
|
||||
# * ps. c2_avg = pul2_Iin
|
||||
# */
|
||||
|
||||
cycle_number = struct.unpack('<H', data[20:22])[0]
|
||||
finish_mode_falg = data[22]
|
||||
battery = struct.unpack('<i', data[23:27])[0]
|
||||
elite_notify_times = data[27]
|
||||
mem_cnt = data[1]
|
||||
time_stamp: float = struct.unpack('<I', data[1+3:5+3])[0]
|
||||
ch1 = struct.unpack('<i', data[5+3:9+3])[0] # unit: nA
|
||||
ch2 = struct.unpack('<i', data[9+3:13+3])[0] # unit: uV
|
||||
ch3 = struct.unpack('<i', data[13+3:17+3])[0] # unit: mOm
|
||||
|
||||
cycle_number = struct.unpack('<H', data[17+3:19+3])[0]
|
||||
finish_mode_falg = data[19+3]
|
||||
battery = struct.unpack('<i', data[20+3:24+3])[0]
|
||||
elite_notify_times = data[24+3]
|
||||
ch4 = struct.unpack('<i', data[25+3:29+3])[0]
|
||||
ch5 = struct.unpack('<i', data[29+3:33+3])[0]
|
||||
ch6 = struct.unpack('<i', data[33+3:37+3])[0]
|
||||
# self._show_data = True
|
||||
|
||||
mem_wrong_information = struct.unpack('<i', data[43:47])[0] # mem_wrong_information = green retry, green wrong, red retry, red wrong
|
||||
|
||||
if mem_wrong_information != self._last_mem_wrong_information:
|
||||
print(datetime.now(), 'device', str(self.device), 'mem_wrong_information[43:47]:', data[43:47], mem_wrong_information, self._last_mem_wrong_information, flush = True)
|
||||
if mem_cnt != self._last_mem_cnt+1:
|
||||
if not (mem_cnt == 0 and self._last_mem_cnt == 255):
|
||||
print(datetime.now(), 'device', str(self.device), 'mem_cnt:', mem_cnt, 'self._last_mem_cnt:', self._last_mem_cnt, flush = True)
|
||||
if (elite_notify_times != self._last_elite_notify_times+1) and not (elite_notify_times == 0 and self._last_elite_notify_times == 0):
|
||||
if not (elite_notify_times == 0 and self._last_elite_notify_times == 255):
|
||||
print(datetime.now(), 'device', str(self.device), 'elite_notify_times:', elite_notify_times, 'self._elite_notify_times:', self._last_elite_notify_times, flush = True)
|
||||
self._last_mem_wrong_information = mem_wrong_information
|
||||
self._last_mem_cnt = mem_cnt
|
||||
self._last_elite_notify_times = elite_notify_times
|
||||
|
||||
ram_num = data[47]
|
||||
broken_flag = data[-1]
|
||||
|
||||
@@ -919,25 +974,31 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
print("error timeStamp full data:", list(data), datetime.now(), '\n')
|
||||
return None
|
||||
else:
|
||||
# print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
|
||||
# '|', current, '|', voltage, '|', impedance,
|
||||
# '|', cycle_number, '|', finishMode, '@', str(self.device))
|
||||
if self._show_data:
|
||||
print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
|
||||
'|', ch1, '|', ch2, '|', ch3, '|', cycle_number,
|
||||
'|', ch4, '|', ch5, '|', ch6,
|
||||
'|', finishMode, '@', str(self.device), flush = True)
|
||||
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:4}'.format(delta),
|
||||
# '|', '{:10}'.format(int(time_stamp * 1000 / 2)),
|
||||
# '|', '{:10}'.format(current),
|
||||
# '|', '{:10}'.format(voltage),
|
||||
# '|', '{:10}'.format(impedance),
|
||||
# '|', '{:5}'.format(cycle_number),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|')
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:4}'.format(delta),
|
||||
# '|', '{:10}'.format(int(time_stamp * 1000 / 2)), #[usec]
|
||||
# '|', '{:10}'.format(ch1), #[nA]
|
||||
# '|', '{:10}'.format(ch2), #[uV]
|
||||
# '|', '{:10}'.format(ch3),
|
||||
# '|', '{:5}'.format(cycle_number),
|
||||
# '|', '{:10}'.format(ch4), #Voutin[uV]
|
||||
# '|', '{:10}'.format(ch5),
|
||||
# '|', '{:10}'.format(ch6),
|
||||
# '|', '{:5}'.format(battery), #[mV]
|
||||
# '|', '{:4}'.format(elite_notify_times),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|', flush = True)
|
||||
|
||||
# print('|', '{:5}'.format(mem_wrong_information),
|
||||
# '|', '{:2}'.format(ram_num),
|
||||
# '|', '{:2}'.format(broken_flag),
|
||||
# '@', str(self.device), '|')
|
||||
pass
|
||||
# print('|', '{:5}'.format(mem_wrong_information),
|
||||
# '|', '{:2}'.format(ram_num),
|
||||
# '|', '{:2}'.format(broken_flag),
|
||||
# '@', str(self.device), '|')
|
||||
|
||||
if finishMode == True:
|
||||
print("finishMode full data:", list(data), datetime.now())
|
||||
@@ -946,10 +1007,13 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
self._mode_stop = 0
|
||||
|
||||
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
|
||||
ret.append_data(0, current)
|
||||
ret.append_data(1, voltage)
|
||||
ret.append_data(2, impedance)
|
||||
ret.append_data(0, ch1)
|
||||
ret.append_data(1, ch2)
|
||||
ret.append_data(2, ch3)
|
||||
ret.append_data(3, cycle_number)
|
||||
ret.append_data(4, ch4)
|
||||
ret.append_data(5, ch5)
|
||||
ret.append_data(6, ch6)
|
||||
# ret.append_data(4, battery)
|
||||
# ret.append_data(5, elite_notify_times)
|
||||
# ret.append_data(6, mem_cnt)
|
||||
@@ -1337,9 +1401,9 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
|
||||
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
|
||||
'_total_time_stamp', '_mode', '_cycle_start_time',
|
||||
'_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff',
|
||||
'cali_coeff', '_ac_amp', '_mode', '_freq_start', '_freq_stop',
|
||||
'_freq_direction', '_last_phase', '_first_phase_flag')
|
||||
'_mode_stop', '_last_time_stamp', '_last_delta',
|
||||
'_cali_package', 'cali_coeff', '_ac_amp', '_mode',
|
||||
'_last_phase', '_first_phase_flag', '_show_data')
|
||||
|
||||
def __init__(self, cali_coeff: bytes = None):
|
||||
super().__init__()
|
||||
@@ -1352,92 +1416,234 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
self._mode_stop = 0
|
||||
|
||||
self._cycle_start_time = []
|
||||
self._ac_amp: 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._first_phase_flag = 1
|
||||
|
||||
self._cali_coeff: Optional[bytes] = None
|
||||
self._cali_package: Optional[bytes] = None
|
||||
self.cali_coeff: Optional[List[Tuple[int, int]]] = None
|
||||
|
||||
if cali_coeff is not None:
|
||||
self._cali_coeff = cali_coeff
|
||||
self.cali_coeff = self._decode_cali_coeff(cali_coeff)
|
||||
self._show_data = False
|
||||
|
||||
if self._cali_package is None:
|
||||
self._cali_package = cali_coeff
|
||||
self.cali_coeff = self._decode_cali_coeff(self._cali_package)
|
||||
|
||||
@staticmethod
|
||||
def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]:
|
||||
if cali_coeff != b'':
|
||||
cis_data_len = 20
|
||||
cali_table = []
|
||||
phase_para_a = []
|
||||
phase_para_b = []
|
||||
hsrtia_a = []
|
||||
hsrtia_b = []
|
||||
hsrtia_c = []
|
||||
hsrtia_d = []
|
||||
rolloff = []
|
||||
phase_coeff = []
|
||||
phase_offset = []
|
||||
|
||||
# print('cali_coeff', cali_coeff)
|
||||
cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4
|
||||
# temp = struct.unpack('>B', cali_coeff[5:6])[0] #1
|
||||
# hsrtia_200r = struct.unpack('>B', cali_coeff[6:7])[0] #1
|
||||
# hsrtia_5k = struct.unpack('>H', cali_coeff[7:9])[0] #2
|
||||
# hsrtia_20k = struct.unpack('>H', cali_coeff[6:8])[0] #2
|
||||
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
|
||||
phase_coeff = numpy.zeros([8, 4], dtype = int)
|
||||
phase_offset = numpy.zeros([8, 4], dtype = int)
|
||||
|
||||
index = 20
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
########################################
|
||||
# phase_coeff
|
||||
# [[freq0, freq1, freq2, freq3] ----->gain0
|
||||
# [freq0, freq1, freq2, freq3] ----->gain1
|
||||
# [freq0, freq1, freq2, freq3] ----->gain2
|
||||
# [freq0, freq1, freq2, freq3] ----->gain3
|
||||
# ]
|
||||
#######################################
|
||||
|
||||
index = 40
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
#hstia=0
|
||||
cis_cali_packet = 1
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
#Lv[0] 160k
|
||||
index = 60
|
||||
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_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
cis_cali_packet = 2
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 0
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 3
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 0
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
#hstia=1
|
||||
cis_cali_packet = 4
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
#Lv[1] 20k
|
||||
index = 80
|
||||
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_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
cis_cali_packet = 5
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 1
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 6
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 1
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
#Lv[2] 5k
|
||||
index = 100
|
||||
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_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
#hstia=2
|
||||
cis_cali_packet = 7
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
#Lv[3] 200R
|
||||
index = 120
|
||||
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_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
cis_cali_packet = 8
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 2
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 9
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 2
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
# hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0])
|
||||
# hsrtia_b.append(struct.unpack('>I', cali_coeff[index+5:index+9])[0]/1e6)
|
||||
# hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e5)
|
||||
# hsrtia_d.append(struct.unpack('>I', cali_coeff[index+13:index+17])[0]/1e6)
|
||||
#hstia=3
|
||||
cis_cali_packet = 10
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
# print('cutoff_freq', cutoff_freq)
|
||||
# print('hsrtia_a', hsrtia_a)
|
||||
# print('hsrtia_b', hsrtia_b)
|
||||
# print('hsrtia_c', hsrtia_c)
|
||||
# print('hsrtia_d', hsrtia_d)
|
||||
# print('phase_para_a', phase_para_a)
|
||||
# print('phase_para_b', phase_para_b)
|
||||
cis_cali_packet = 11
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 3
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 12
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 3
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cali_table.append((cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
|
||||
#hstia=4
|
||||
cis_cali_packet = 13
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
cis_cali_packet = 14
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 4
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 15
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 4
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
#hstia=5
|
||||
cis_cali_packet = 16
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
cis_cali_packet = 17
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 5
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 18
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 5
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
#hstia=6
|
||||
cis_cali_packet = 19
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
cis_cali_packet = 20
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 6
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 21
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 6
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
#hstia=7
|
||||
cis_cali_packet = 22
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
|
||||
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
|
||||
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
|
||||
|
||||
cis_cali_packet = 23
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 7
|
||||
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
|
||||
cis_cali_packet = 24
|
||||
index = (cis_cali_packet - 1) * cis_data_len
|
||||
g = 7
|
||||
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
|
||||
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
|
||||
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
|
||||
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
|
||||
print('hsrtia_a', hsrtia_a)
|
||||
print('hsrtia_b', hsrtia_b)
|
||||
print('rolloff', rolloff)
|
||||
print('phase_coeff')
|
||||
print(phase_coeff)
|
||||
print('phase_offset')
|
||||
print(phase_offset)
|
||||
|
||||
cali_table.append((phase_coeff, phase_offset, hsrtia_a, hsrtia_b, rolloff))
|
||||
|
||||
return cali_table
|
||||
else:
|
||||
@@ -1446,10 +1652,10 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
|
||||
@property
|
||||
def name(self) -> AnyStr:
|
||||
if self._cali_coeff is None:
|
||||
if self._cali_package is None:
|
||||
return self.NAME
|
||||
else:
|
||||
return self.NAME.encode() + b':' + self._cali_coeff
|
||||
return self.NAME.encode() + b':' + self._cali_package
|
||||
|
||||
def message(self) -> Optional[str]:
|
||||
ret = self._message
|
||||
@@ -1467,9 +1673,14 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
time_stamp: float = struct.unpack('<I', data[13+3:17+3])[0] # unit: ms
|
||||
cycle_number = struct.unpack('>H', data[17+3:19+3])[0]
|
||||
d19 = data[19+3]
|
||||
gain = (d19 & 0x0F)
|
||||
finishMode = (d19 & 0x80) >> 7
|
||||
gain = data[20+3]
|
||||
finishMode = (d19 & 0x80) >> 7
|
||||
ch4 = struct.unpack('<i', data[21+3:25+3])[0] # Amp[uV]
|
||||
|
||||
notify_one = struct.unpack('<i', data[25+3:29+3])[0]
|
||||
notify_two = struct.unpack('<i', data[29+3:33+3])[0]
|
||||
notify_three = struct.unpack('<i', data[33+3:37+3])[0]
|
||||
|
||||
if time_stamp == 0:
|
||||
self._start_return_data = True
|
||||
|
||||
@@ -1477,7 +1688,7 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
return None
|
||||
|
||||
if time_stamp != 0 and self._start_return_data == True:
|
||||
if (self._mode == 0):
|
||||
if (self._mode == 0 or self._mode == 5):
|
||||
time_stamp, delta, ret_get_time_stamp = self.eis_get_time_stamp(time_stamp)
|
||||
else:
|
||||
time_stamp, delta, ret_get_time_stamp = self.get_time_stamp(time_stamp)
|
||||
@@ -1486,101 +1697,83 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
print("error timeStamp full data:", list(data), datetime.now(), '\n')
|
||||
return None
|
||||
else:
|
||||
if self.cali_coeff is not None and self._mode == 0:
|
||||
phase_para_a = []
|
||||
phase_para_b = []
|
||||
if self.cali_coeff is not None and (self._mode == 0 or self._mode == 5):
|
||||
hsrtia_a = []
|
||||
hsrtia_b = []
|
||||
hsrtia_c = []
|
||||
hsrtia_d = []
|
||||
cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
|
||||
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
|
||||
rolloff = []
|
||||
phase_coeff, phase_offset, hsrtia_a, hsrtia_b, rolloff = self.cali_coeff[0]
|
||||
|
||||
if (self._mode == 0):
|
||||
if (self._mode == 0 or self._mode == 5):
|
||||
img = ch1
|
||||
real = ch2
|
||||
freq = ch3
|
||||
fre_idx = 0
|
||||
voltage_amp = round(ch4 / 1000) # Amp[mV]
|
||||
rolloff_cali = rolloff[gain]
|
||||
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2)
|
||||
|
||||
# if (gain == 3):
|
||||
# current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag)
|
||||
# else:
|
||||
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
|
||||
# print(current)
|
||||
# print(voltage_mag)
|
||||
# print(hsrtia_a[gain])
|
||||
# print(hsrtia_b[gain])
|
||||
# print(hsrtia_c[gain])
|
||||
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / rolloff_cali ** 2 / 1e4)
|
||||
current = (voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain]) / 1e8 #[nA]
|
||||
|
||||
if (current != 0):
|
||||
# impedance = voltage_amp * 1000_000 / 1.414213 / current
|
||||
impedance = voltage_amp * 707106.78 / current
|
||||
# impedance[mOhm] = voltage_amp[mv] * 1000000 / 1.414213 / current[nA] #RMS=amp*SQRT(2), SQRT(2)=1.414213
|
||||
impedance = voltage_amp * 707106.78 / current
|
||||
else:
|
||||
impedance = 0
|
||||
|
||||
if (real > 0):
|
||||
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
|
||||
raw_phase = math.atan2(img , real) * 180 / math.pi
|
||||
|
||||
if (freq >= 1000000): # 10000 Hz
|
||||
i = 0
|
||||
fre_idx = 0
|
||||
elif (freq >= 10000): # 100 Hz
|
||||
i = 1
|
||||
fre_idx = 1
|
||||
elif (freq >= 1000): # 10 Hz
|
||||
i = 2
|
||||
fre_idx = 2
|
||||
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 = phase % 180 if phase % 180<=90 else phase % 180-180
|
||||
|
||||
if (self._first_phase_flag):
|
||||
self._last_phase = phase
|
||||
self._first_phase_flag = 0
|
||||
elif (abs(phase - self._last_phase) >= 200):
|
||||
phase -= 360
|
||||
self._last_phase = phase
|
||||
imag_after_cal = round(impedance * math.sin(phase * math.pi / 180))
|
||||
real_after_cal = round(impedance * math.cos(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)
|
||||
if self._show_data:
|
||||
if (self._mode == 0 or self._mode == 5):
|
||||
print('|', '{:10}'.format(time_stamp),
|
||||
'|', '{:5}'.format(delta),
|
||||
'|', '{:5}'.format(ch1), #raw_img
|
||||
'|', '{:5}'.format(ch2), #raw_real
|
||||
'|', '{:8}'.format(ch3 * 10), '[mHz]', #Frequency [mHz]
|
||||
'|', '{:5}'.format(cycle_number), #cycle
|
||||
'|', '{:5}'.format(round(imag_after_cal)), '[Ohm]', #Z_imag [Ohm]
|
||||
'|', '{:5}'.format(round(real_after_cal)), '[Ohm]', #Z_real [Ohm]
|
||||
'|', '{:5}'.format(round(impedance)), '[Ohm]', #Impedance [Ohm]
|
||||
'|', '{:5}'.format(round(phase*1000)), '[mdegree]', #Phase [millidegree]
|
||||
'|', '{:5}'.format(round(current)), '[nA]', #Current [nA]
|
||||
'|', '{:1}'.format(gain), #gain
|
||||
'|', '{:1}'.format(finishMode), #finishMode
|
||||
'@', str(self.device), '|', flush = True)
|
||||
|
||||
|
||||
if (self._mode == 0):
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:5}'.format(delta),
|
||||
# '|', '{:6}'.format(ch1),
|
||||
# '|', '{:6}'.format(ch2),
|
||||
# '|', '{:8}'.format(ch3 / 100),
|
||||
# '|', '{:6}'.format(round(voltage_mag)),
|
||||
# '|', '{:5}'.format(int(imag_after_cal)),
|
||||
# '|', '{:5}'.format(int(real_after_cal)),
|
||||
# '|', '{:5}'.format(round(impedance)),
|
||||
# '|', '{:5}'.format(round(phase, 1)),
|
||||
# '|', '{:5}'.format(round(current, 3)),
|
||||
# '|', '{:1}'.format(gain),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|')
|
||||
pass
|
||||
else:
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:5}'.format(delta),
|
||||
# '|', '{:5}'.format(ch1),
|
||||
# '|', '{:5}'.format(ch2),
|
||||
# '|', '{:5}'.format(ch3),
|
||||
# '|', '{:5}'.format(cycle_number),
|
||||
# '|', '{:1}'.format(gain),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|')
|
||||
pass
|
||||
print('|', '{:10}'.format(time_stamp),
|
||||
'|', '{:5}'.format(delta),
|
||||
'|', '{:5}'.format(notify_one),
|
||||
'|', '{:5}'.format(notify_two),
|
||||
'|', '{:5}'.format(notify_three),
|
||||
'|', '{:5}'.format(voltage_amp), #amp[mV]
|
||||
'|', flush = True)
|
||||
pass
|
||||
else:
|
||||
print('|', '{:10}'.format(time_stamp),
|
||||
'|', '{:5}'.format(delta),
|
||||
'|', '{:5}'.format(ch1),
|
||||
'|', '{:5}'.format(ch2),
|
||||
'|', '{:5}'.format(ch3),
|
||||
'|', '{:5}'.format(cycle_number),
|
||||
'|', '{:1}'.format(gain),
|
||||
'|', '{:1}'.format(finishMode),
|
||||
'@', str(self.device), '|', flush = True)
|
||||
pass
|
||||
|
||||
if finishMode == True:
|
||||
print("finishMode full data:", list(data), datetime.now())
|
||||
@@ -1589,23 +1782,29 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
self._mode_stop = 0
|
||||
|
||||
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
|
||||
if (self._mode == 0): #EIS Mode
|
||||
ret.append_data(3, cycle_number)
|
||||
ret.append_data(0, ch1) #Raw Imag
|
||||
ret.append_data(1, ch2) #Raw Real
|
||||
if self._mode == 0 or self._mode == 5:
|
||||
ret.append_data(0, ch1) #raw_img
|
||||
ret.append_data(1, ch2) #raw_real
|
||||
ret.append_data(2, ch3 * 10) #Frequency [mHz]
|
||||
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(3, cycle_number) #cycle
|
||||
ret.append_data(4, imag_after_cal) #Z_imag [Ohm]
|
||||
ret.append_data(5, real_after_cal) #Z_real [Ohm]
|
||||
ret.append_data(6, round(impedance)) #Impedance [Ohm]
|
||||
ret.append_data(7, round(phase)) #Phase [degree]
|
||||
ret.append_data(7, round(phase*1000)) #Phase [millidegree]
|
||||
ret.append_data(8, round(current)) #Current [nA]
|
||||
ret.append_data(9, gain) #Gain Level
|
||||
ret.append_data(9, gain) #gain
|
||||
|
||||
#debug data
|
||||
ret.append_data(10, notify_one)
|
||||
ret.append_data(11, notify_two)
|
||||
ret.append_data(12, notify_three)
|
||||
ret.append_data(13, voltage_amp) #amp[mV]
|
||||
|
||||
else: #CV Mode
|
||||
ret.append_data(3, cycle_number)
|
||||
ret.append_data(0, ch1) #Iin [nA]
|
||||
ret.append_data(1, ch2) #Vset [nV]
|
||||
ret.append_data(2, ch3) #Vout [nV]
|
||||
ret.append_data(3, cycle_number)
|
||||
|
||||
if cycle_number != self._cycle_number:
|
||||
# notify cycle_number change
|
||||
|
||||
@@ -651,17 +651,9 @@ class DeviceInstruction:
|
||||
VIS_DEVICE_DONE = 0x20
|
||||
"""identify device done"""
|
||||
|
||||
VIS_CC_ZERO = 0x40
|
||||
|
||||
VIS_ASK = 0x30
|
||||
"""ask in virtual instruction"""
|
||||
|
||||
VIS_STI = 0xC0
|
||||
"""stimulation on virtual instruction"""
|
||||
|
||||
VIS_FUH = 0x90
|
||||
"""flush virtual instruction"""
|
||||
|
||||
VIS_INT = 0x60
|
||||
"""interrupt virtual instruction"""
|
||||
|
||||
@@ -697,11 +689,13 @@ class DeviceInstruction:
|
||||
TYP_IIS = -1
|
||||
"""internal instruction"""
|
||||
|
||||
TYP_ALL = None
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@classmethod
|
||||
def valid_ins_type(cls, ins_type: int):
|
||||
if ins_type not in (cls.TYP_RIS, cls.TYP_VIS, cls.TYP_CIS, cls.TYP_IIS):
|
||||
if ins_type not in (cls.TYP_RIS, cls.TYP_VIS, cls.TYP_CIS, cls.TYP_IIS, cls.TYP_ALL):
|
||||
raise ValueError('unknown instruction type : ' + str(ins_type))
|
||||
|
||||
@classmethod
|
||||
@@ -712,6 +706,8 @@ class DeviceInstruction:
|
||||
return cls.TYP_VIS
|
||||
elif ins_type == 'CIS':
|
||||
return cls.TYP_CIS
|
||||
elif ins_type == 'ALL':
|
||||
return cls.TYP_ALL
|
||||
else:
|
||||
raise RuntimeError('unknown instruction type : ' + ins_type)
|
||||
|
||||
@@ -732,7 +728,6 @@ class DeviceCommonInstruction:
|
||||
STOP_STIMULATE = "stop_stimulate"
|
||||
VIS_DEVICE_DETECT = 'VIS_DEVICE_DETECT'
|
||||
VIS_DEVICE_DONE = 'VIS_DEVICE_DONE'
|
||||
VIS_CC_ZERO = 'VIS_CC_ZERO'
|
||||
CIS_VOLT = 'CIS_VOLT'
|
||||
CIS_VERSION = 'CIS_VERSION'
|
||||
|
||||
@@ -747,19 +742,15 @@ class DeviceCommonInstruction:
|
||||
elif instruction == cls.START:
|
||||
return '_data_format("TDC4VAF2")', '_notify(True)', 'VIS_STI', '_sync(True)'
|
||||
elif instruction == cls.INTERRUPT:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
return '_notify(False)', 'VIS_INT', '_sync(False)'
|
||||
elif instruction == cls.CLOSE:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
elif instruction == cls.FLUSH:
|
||||
return 'VIS_FUH',
|
||||
elif instruction == cls.CALL:
|
||||
return 'VIS_CAL',
|
||||
elif instruction == cls.VIS_DEVICE_DETECT:
|
||||
return 'VIS_DEVICE_DETECT',
|
||||
elif instruction == cls.VIS_DEVICE_DONE:
|
||||
return 'VIS_DEVICE_DONE',
|
||||
elif instruction == cls.VIS_CC_ZERO:
|
||||
return 'VIS_CC_ZERO',
|
||||
elif instruction == cls.RECORD:
|
||||
return 'VIS_STARTR',
|
||||
elif instruction == cls.RECORD_ALL:
|
||||
|
||||
@@ -4,6 +4,7 @@ from biopro.util.text import part_suffix
|
||||
from . import *
|
||||
from .expression import *
|
||||
|
||||
import json
|
||||
|
||||
class DeviceParameterError(RuntimeError):
|
||||
__slots__ = ()
|
||||
@@ -119,6 +120,9 @@ class ParameterDomain(JsonSerialize, metaclass=abc.ABCMeta):
|
||||
elif json == 'int':
|
||||
return ParameterIntDomain
|
||||
|
||||
elif json == 'float':
|
||||
return ParameterFloatDomain
|
||||
|
||||
elif json == 'property':
|
||||
return ParameterPropertyDomain
|
||||
|
||||
@@ -290,6 +294,25 @@ class ParameterIntDomainType(ParameterTypeDomain):
|
||||
|
||||
ParameterIntDomain = ParameterIntDomainType()
|
||||
|
||||
class ParameterFloatDomainType(ParameterTypeDomain):
|
||||
__slots__ = ()
|
||||
|
||||
def init_para(self, initial: Optional[Any] = None) -> float:
|
||||
print('ParameterFloatDomainType')
|
||||
if initial is None:
|
||||
return 0
|
||||
else:
|
||||
return float(initial)
|
||||
|
||||
def valid_para(self, value: int) -> bool:
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return "float"
|
||||
|
||||
|
||||
ParameterFloatDomain = ParameterFloatDomainType()
|
||||
|
||||
|
||||
class ParameterValueDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
"""limited/ranged P value domain """
|
||||
@@ -300,7 +323,7 @@ class ParameterValueDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
if initial is None:
|
||||
return self.range[0]
|
||||
else:
|
||||
initial = int(initial)
|
||||
initial = initial
|
||||
f, t = self.range
|
||||
|
||||
if f <= initial < t:
|
||||
@@ -309,6 +332,8 @@ class ParameterValueDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
return f
|
||||
|
||||
def valid_para(self, value: Any) -> bool:
|
||||
if isinstance(value, list):
|
||||
return True
|
||||
f, t = self.range
|
||||
return f <= float(value) < t
|
||||
|
||||
@@ -489,8 +514,12 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
|
||||
@classmethod
|
||||
def parse(cls, expr: Union[int, str]) -> 'ParameterCollectionValueOperator':
|
||||
# parse epression then create value_operator
|
||||
if isinstance(expr, int):
|
||||
return SingleValueOperator(None, expr)
|
||||
|
||||
elif isinstance(expr, list):
|
||||
return CollectValueOperator((0, len(expr)), expr)
|
||||
|
||||
elif expr == '*':
|
||||
return AddAllValueOperator
|
||||
@@ -498,6 +527,10 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
elif expr == ':=':
|
||||
return CollectValueOperator((None, None), [])
|
||||
|
||||
elif '[' in expr and ']' in expr:
|
||||
v = json.loads(expr)
|
||||
return CollectValueOperator((0, len(v)), v)
|
||||
|
||||
elif '=' in expr:
|
||||
a, v = part_suffix(expr, '=')
|
||||
|
||||
@@ -508,6 +541,7 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
return CollectValueOperator((None, None), v)
|
||||
|
||||
else:
|
||||
# get list length (old way)
|
||||
a, b = part_suffix(a, ':')
|
||||
a = int(a) if len(a) else None
|
||||
b = int(b) if len(b) else None
|
||||
@@ -602,8 +636,8 @@ class ParameterCollectionDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
def __init__(self, domain: ParameterDomain):
|
||||
super().__init__()
|
||||
|
||||
if isinstance(domain, ParameterCollectionDomain):
|
||||
raise RuntimeError('cannot compose with parameter collection domain')
|
||||
# if isinstance(domain, ParameterCollectionDomain):
|
||||
# raise RuntimeError('cannot compose with parameter collection domain')
|
||||
|
||||
self._domain = domain
|
||||
|
||||
@@ -725,10 +759,12 @@ class ParameterListDomain(ParameterCollectionDomain):
|
||||
if oper == AddAllValueOperator:
|
||||
raise ValueError("list parameter cannot accept '*' (all) value")
|
||||
|
||||
# d: domain, sz: lsit length, i: slice(a, b), v: list value
|
||||
d = self.element_domain
|
||||
sz = len(target)
|
||||
i = oper.index(sz)
|
||||
v = oper.value(d)
|
||||
# print('ParameterListDomain', d, sz, i, v, str(d) == 'float', type(d))
|
||||
|
||||
if i is None and v is None:
|
||||
pass
|
||||
@@ -767,8 +803,11 @@ class ParameterListDomain(ParameterCollectionDomain):
|
||||
|
||||
if isinstance(v, int):
|
||||
v = [v]
|
||||
|
||||
target[i] = v
|
||||
target[len(v):] = []
|
||||
if isinstance(d, ParameterFloatDomainType):
|
||||
target[i] = [float(i) for i in v]
|
||||
else:
|
||||
target[i] = v
|
||||
|
||||
def _valid_list_limit(self, target: List[Any], inc: int) -> bool:
|
||||
if self._limit is not None:
|
||||
|
||||
@@ -119,7 +119,10 @@ class DeviceConfigurationEncoder:
|
||||
e.write(b'L\0')
|
||||
|
||||
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(parameter_type.encode())
|
||||
e.u8(sz)
|
||||
@@ -153,7 +156,8 @@ class DeviceConfigurationEncoder:
|
||||
if isinstance(value, bool):
|
||||
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)
|
||||
|
||||
elif isinstance(value, int):
|
||||
@@ -170,7 +174,7 @@ class DeviceConfigurationEncoder:
|
||||
if isinstance(value, bool):
|
||||
return '?'
|
||||
|
||||
elif isinstance(value, str):
|
||||
elif isinstance(value, str) or isinstance(value, list):
|
||||
return 'p'
|
||||
|
||||
elif isinstance(value, int):
|
||||
|
||||
@@ -880,8 +880,7 @@ class WhenExpression(ComplexExpression[T]):
|
||||
|
||||
def value(self, context: Scope) -> Union[str, T]:
|
||||
value = super().value(context)
|
||||
|
||||
key = str(value)
|
||||
key = str(int(value))
|
||||
|
||||
if key in self._when:
|
||||
return self._when[key].value(context.child(VALUE=value))
|
||||
|
||||
@@ -5,6 +5,13 @@ from .device import *
|
||||
from .instruction import *
|
||||
from .parameter import *
|
||||
|
||||
def convert_to_float(lst):
|
||||
# Check if the element is a list (for handling nested lists)
|
||||
if isinstance(lst, list):
|
||||
return [convert_to_float(x) for x in lst]
|
||||
else:
|
||||
# If it's not a list, convert it to float
|
||||
return float(lst)
|
||||
|
||||
class MatchRule(JsonSerialize, metaclass=abc.ABCMeta):
|
||||
"""Device matching rule. Program use this table to find correct library according to the response information from
|
||||
@@ -444,6 +451,12 @@ class DefaultLibraryLoader:
|
||||
|
||||
elif guard is not None:
|
||||
guard = ListGuardExpression([GuardExpression.parse(guard)])
|
||||
|
||||
if "float" in str(domain):
|
||||
initial = convert_to_float(initial)
|
||||
|
||||
# print('!@#$%^&')
|
||||
# print(name, domain, initial, value, value_set)
|
||||
|
||||
return ParameterInfo(name, domain,
|
||||
initial=initial,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import re
|
||||
import struct
|
||||
from random import randint
|
||||
from time import sleep
|
||||
from typing import Sequence, Tuple
|
||||
@@ -283,6 +284,8 @@ class InternalInstruction(SingleInstruction):
|
||||
PREDEFINED_SET = '_set'
|
||||
PREDEFINED_CDR = '_cdr'
|
||||
PREDEFINED_DISABLE_CACHE = '_disable_cache'
|
||||
PREDEFINED_IDLE = '_idle'
|
||||
PREDEFINED_COUNTDOWN = '_countdown'
|
||||
|
||||
PREDEFINED = (
|
||||
PREDEFINED_SLEEP,
|
||||
@@ -294,6 +297,8 @@ class InternalInstruction(SingleInstruction):
|
||||
PREDEFINED_SET,
|
||||
PREDEFINED_CDR,
|
||||
PREDEFINED_DISABLE_CACHE,
|
||||
PREDEFINED_IDLE,
|
||||
PREDEFINED_COUNTDOWN
|
||||
)
|
||||
|
||||
__slots__ = ('_expr', '_para')
|
||||
@@ -373,7 +378,7 @@ class InternalInstruction(SingleInstruction):
|
||||
|
||||
parser.parse_instruction(context, data)
|
||||
|
||||
|
||||
# tag2
|
||||
class ListInstruction(Instruction, ImmutableListNode[Union[Instruction, Expression[str]]]):
|
||||
"""Instruction group, allow the name of the instruction or a expression it.
|
||||
If instruction name is ``None``, ignore it.
|
||||
@@ -586,7 +591,7 @@ class InstructionContentWidth:
|
||||
|
||||
return InstructionContentWidth(z, t, signed_value=s is not None, little_endian=e == '<'), x
|
||||
|
||||
|
||||
# The start from the json file parse
|
||||
class InstructionContent(JsonSerialize):
|
||||
"""
|
||||
**json format**
|
||||
@@ -680,7 +685,7 @@ class InstructionContent(JsonSerialize):
|
||||
|
||||
return ins_type(width, expr, **ins_argv, comment=comment)
|
||||
|
||||
|
||||
# tag1
|
||||
class InstructionDataContent(InstructionContent):
|
||||
"""
|
||||
**json format**
|
||||
@@ -741,6 +746,7 @@ class InstructionDataContent(InstructionContent):
|
||||
return ret[index]
|
||||
|
||||
def build_instruction(self, context: Scope, buffer: List[int], shift: int = 0) -> int:
|
||||
# print('build_instruction', context, buffer, shift, self.value(context))
|
||||
if self._width.is_array:
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -748,24 +754,33 @@ class InstructionDataContent(InstructionContent):
|
||||
value = 1
|
||||
elif self.value(context) == 'false':
|
||||
value = 0
|
||||
elif isinstance(self.value(context), list):
|
||||
value = self.value(context)
|
||||
else:
|
||||
value = int(self.value(context))
|
||||
value = self.value(context)
|
||||
# print('value', value, type(value))
|
||||
# print('self._width.bytes_unit', self._width.bytes_unit)
|
||||
# print('self._width.size', self._width.size)
|
||||
|
||||
if self._width.bytes_unit:
|
||||
if self._width.size == 1:
|
||||
buffer.append(value)
|
||||
|
||||
else:
|
||||
tmp = []
|
||||
for _ in range(self._width.size):
|
||||
tmp.append(value & 0xFF)
|
||||
value >>= 8
|
||||
|
||||
if self._width.little_endian:
|
||||
buffer.extend(tmp)
|
||||
else:
|
||||
buffer.extend(tmp[::-1])
|
||||
if isinstance(self.value(context), list):
|
||||
buffer.extend(value)
|
||||
elif isinstance(value, int):
|
||||
tmp = []
|
||||
for _ in range(self._width.size):
|
||||
tmp.append(value & 0xFF)
|
||||
value >>= 8
|
||||
|
||||
if self._width.little_endian:
|
||||
buffer.extend(tmp)
|
||||
else:
|
||||
buffer.extend(tmp[::-1])
|
||||
elif isinstance(value, float):
|
||||
buffer.extend(struct.pack('>f', value))
|
||||
return 8
|
||||
|
||||
else:
|
||||
@@ -792,6 +807,7 @@ class InstructionDataContent(InstructionContent):
|
||||
offset += 1
|
||||
|
||||
else:
|
||||
buffer.extend([0]*(self._width.size-len(buffer)))
|
||||
for i in range(self._width.size):
|
||||
if self._width.little_endian:
|
||||
value |= (buffer[offset] << (1 * i))
|
||||
@@ -1109,7 +1125,7 @@ class SendInstruction(SingleInstruction):
|
||||
else:
|
||||
for scope in self._foreach_parameter.for_scope(context):
|
||||
yield ResolvedSendInstruction(self, self._build_instruction(scope))
|
||||
|
||||
# tag3
|
||||
def _build_instruction(self, context: Scope) -> List[int]:
|
||||
buffer = []
|
||||
shift = 0
|
||||
|
||||
@@ -359,6 +359,7 @@ class DeviceParameter(JsonSerialize):
|
||||
|
||||
# initial parameter table
|
||||
for para_info in library.parameter_table.values():
|
||||
# print('DeviceParameter', para_info)
|
||||
try:
|
||||
para_value = para_info.init_para()
|
||||
|
||||
@@ -510,9 +511,10 @@ class DeviceParameter(JsonSerialize):
|
||||
:param para: parameter name
|
||||
:param oper: operator expression
|
||||
"""
|
||||
# parse operator return CollectValueOperator instance
|
||||
if not isinstance(oper, ParameterCollectionValueOperator):
|
||||
oper = ParameterCollectionValueOperator.parse(oper)
|
||||
|
||||
|
||||
table = self._library.parameter_table
|
||||
info = table[para]
|
||||
domain = info.domain
|
||||
@@ -521,6 +523,7 @@ class DeviceParameter(JsonSerialize):
|
||||
raise RuntimeError('not a collection parameter ' + para)
|
||||
|
||||
target = self._parameter[para]
|
||||
# print(table, info, domain, target, str(domain) == '[float]', oper)
|
||||
|
||||
if isinstance(target, set):
|
||||
old = set(target)
|
||||
@@ -528,6 +531,7 @@ class DeviceParameter(JsonSerialize):
|
||||
old = list(target)
|
||||
|
||||
try:
|
||||
# replace target with new oper
|
||||
domain.oper_para(target, oper, self._context)
|
||||
except RuntimeError as e:
|
||||
raise IllegalParameterValueError(para, str(oper)) from e
|
||||
@@ -966,7 +970,7 @@ class CompletedDevice(Device):
|
||||
"""
|
||||
__slots__ = ('_master', '_device_id', '_device', '_library', '_context',
|
||||
'_parameter', '_configuration', '_lock', '_feature_mask',
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status')
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project')
|
||||
|
||||
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
|
||||
"""
|
||||
@@ -984,6 +988,8 @@ class CompletedDevice(Device):
|
||||
|
||||
# device status ( 0: idle, 1: working, 2: error, 3: power off)
|
||||
self._status = 0
|
||||
# device be occupied by project
|
||||
self._occupied_by_project = None
|
||||
|
||||
# context
|
||||
s1 = library.constant
|
||||
@@ -1030,7 +1036,7 @@ class CompletedDevice(Device):
|
||||
|
||||
@property
|
||||
def mac_address_in_str(self) -> str:
|
||||
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address)
|
||||
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address).upper()
|
||||
|
||||
@property
|
||||
def device(self) -> Device:
|
||||
@@ -1080,6 +1086,14 @@ class CompletedDevice(Device):
|
||||
def status(self, new_status):
|
||||
self._status = new_status
|
||||
|
||||
@property
|
||||
def occupied_by_project(self) -> str:
|
||||
return self._occupied_by_project
|
||||
|
||||
@occupied_by_project.setter
|
||||
def occupied_by_project(self, new_occupied_by_project):
|
||||
self._occupied_by_project = new_occupied_by_project
|
||||
|
||||
# device parameter getter/setter
|
||||
|
||||
def parameters(self) -> List[str]:
|
||||
@@ -1103,6 +1117,8 @@ class CompletedDevice(Device):
|
||||
return self._configuration.get_parameter(name, False)
|
||||
|
||||
def set_multi_parameters(self, parameter):
|
||||
if len(parameter) == 0:
|
||||
return
|
||||
for (name, value) in parameter[0].items():
|
||||
if name != 'target':
|
||||
self.set_parameter(name, value)
|
||||
@@ -1114,18 +1130,31 @@ class CompletedDevice(Device):
|
||||
:param value: new parameter P value
|
||||
"""
|
||||
info = self._library.parameter_table[name]
|
||||
# print('info', info.domain, info.domain == 'float', info.domain == '[float]')
|
||||
|
||||
if isinstance(info.domain, ParameterCollectionDomain):
|
||||
self._parameter.oper_parameter(name, value)
|
||||
elif isinstance(info.domain, ParameterFloatDomainType):
|
||||
self._parameter.set_parameter(name, float(value))
|
||||
else:
|
||||
try:
|
||||
value = value
|
||||
# value int
|
||||
value = int(value)
|
||||
if isinstance(value, str):
|
||||
if "." in value:
|
||||
value = float(value)
|
||||
else:
|
||||
value = int(value)
|
||||
except ValueError as e:
|
||||
# value float
|
||||
self._parameter.set_parameter(name, value)
|
||||
# raise RuntimeError('illegal parameter value : ' + value) from e
|
||||
else:
|
||||
if name == 'MODE':
|
||||
if self.library_name.startswith('Elite_EDC') or 'EIS' in self.library_name:
|
||||
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)
|
||||
|
||||
on_change = info.on_change
|
||||
@@ -1294,6 +1323,7 @@ class CompletedDevice(Device):
|
||||
'recording_file_name': self.recording_file_name,
|
||||
'library_name': self._library.name,
|
||||
'library_version': str(self._library.version),
|
||||
'occupied_by_project': self._occupied_by_project,
|
||||
'configuration': self.configuration.as_json(list_hide=True),
|
||||
}
|
||||
|
||||
@@ -1383,20 +1413,6 @@ class DebugDevice(CompletedDevice):
|
||||
def read_command_return_data(self) -> Optional[bytes]:
|
||||
return None
|
||||
|
||||
def send_command(self, ins_type: int, ins_oper: int, *instruction: int):
|
||||
length = len(instruction)
|
||||
print('instruction send :',
|
||||
'%02X' % ((ins_type & 0xF0) | (self.device_id & 0x0F)),
|
||||
'%02X' % ((ins_oper & 0xF0) | (length & 0x0F)),
|
||||
' '.join(map(lambda v: '%02X' % v, instruction)))
|
||||
|
||||
def send_instruction(self, ins_type: int, ins_oper: int, *instruction: int):
|
||||
length = len(instruction)
|
||||
print('instruction send :',
|
||||
'%02X' % ((ins_type & 0xF0) | (self.device_id & 0x0F)),
|
||||
'%02X' % ((ins_oper & 0xF0) | (length & 0x0F)),
|
||||
' '.join(map(lambda v: '%02X' % v, instruction)))
|
||||
|
||||
@property
|
||||
def battery(self) -> int:
|
||||
return 100
|
||||
|
||||
@@ -433,6 +433,7 @@ class ParameterInfo(JsonSerialize):
|
||||
return self._on_change
|
||||
|
||||
def init_para(self) -> Any:
|
||||
# print('initial', self._name, self._initial)
|
||||
"""
|
||||
:return: initial P value
|
||||
:raises value: illegal initial value
|
||||
@@ -617,6 +618,7 @@ class ParameterInfo(JsonSerialize):
|
||||
return []
|
||||
|
||||
elif isinstance(self._value, ComplexExpression):
|
||||
print('cast_value_dependency', self._value.dependency)
|
||||
return self._value.dependency
|
||||
|
||||
else:
|
||||
|
||||
@@ -3697,7 +3697,6 @@ class CC2650Central(LoggerFlag):
|
||||
|
||||
def recv(self, timeout: Optional[float] = None) -> Optional[list]:
|
||||
packet = self._recv_byte()
|
||||
# print("packet = ", packet)
|
||||
|
||||
if packet is None:
|
||||
return None
|
||||
@@ -3709,6 +3708,8 @@ class CC2650Central(LoggerFlag):
|
||||
|
||||
def _recv_byte(self) -> Optional[int]:
|
||||
ret = self._recv_bytes(1)
|
||||
# if ret is not None:
|
||||
# print('packet = {0}'.format(hex(ret[0]).upper()))
|
||||
return ret[0] if ret is not None else None
|
||||
|
||||
def _recv_bytes(self, size: int = 1) -> Union[None, bytes]:
|
||||
@@ -3724,27 +3725,28 @@ class CC2650Central(LoggerFlag):
|
||||
return None
|
||||
|
||||
def _recv_event(self, timeout: Optional[float] = 1) -> Optional[list]:
|
||||
code = self._recv_byte()
|
||||
# print("code = ", code)
|
||||
packet = self._recv_byte()
|
||||
|
||||
if code is None:
|
||||
if packet is None:
|
||||
return None
|
||||
|
||||
length = self._recv_byte()
|
||||
# print('code::',code,'length::',length)
|
||||
|
||||
_start = _time()
|
||||
len_b = _struct.pack("B", length)
|
||||
data = b''
|
||||
|
||||
while len(data) < length:
|
||||
ret = self._recv_bytes(length - len(data))
|
||||
# print("ret = ", ret)
|
||||
_start = _time()
|
||||
|
||||
if ret is not None:
|
||||
data += ret
|
||||
while len(data) < length:
|
||||
packets = self._recv_bytes(length - len(data))
|
||||
# hex_packets = ''.join(format(i, '02x') for i in packets)
|
||||
# print("packets = ", hex_packets.upper())
|
||||
|
||||
if packets is not None:
|
||||
data += packets
|
||||
elif timeout is not None and _time() - _start > timeout:
|
||||
raise RecvTimeout()
|
||||
|
||||
data = len_b + data
|
||||
self._interface.flush()
|
||||
return list(data)
|
||||
|
||||
@@ -3760,5 +3762,7 @@ class CC2650Central(LoggerFlag):
|
||||
raise RecvTimeout()
|
||||
|
||||
else:
|
||||
uart_data_hex = ''.join(format(i, '02X') for i in uart_data)
|
||||
# print('uart_data: 0x{0}'.format(uart_data_hex.upper()))
|
||||
return uart_data
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ MSM_REG_WRITE = 0x01
|
||||
MEM_INS_WRITE = 0x02
|
||||
MEM_INS_READ = 0x03
|
||||
MEM_REG_READ = 0x05
|
||||
DEFAULT_REGISTER_VALUE = 0b0100_0011 # 67
|
||||
DEFAULT_REGISTER_VALUE = 0b0100_0001 # 0x41
|
||||
MEM_SIZE = 0x1000
|
||||
|
||||
_SLEEP_TIME_ = 0.001
|
||||
@@ -35,7 +35,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
'_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value',
|
||||
'_read_green_times','_read_red_times',
|
||||
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
|
||||
'_head_wrong_cnt')
|
||||
'_head_wrong_cnt', '_pin_busy_value')
|
||||
|
||||
def __init__(self,
|
||||
select: Selector,
|
||||
@@ -50,11 +50,11 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
||||
|
||||
# buffer
|
||||
self._tx_buffer_header = [0] * 19
|
||||
self._tx_buffer_header = [0] * 64
|
||||
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
|
||||
|
||||
# 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_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
|
||||
@@ -62,6 +62,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
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_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_red_times = 0
|
||||
@@ -76,6 +77,8 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
def set_pin_mem_req(self, value: bool):
|
||||
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_value[channel] = value
|
||||
|
||||
@@ -96,6 +99,14 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._pin_ram_sel_value[channel] = True
|
||||
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
|
||||
def select(self) -> int:
|
||||
return self._selector.channel
|
||||
@@ -214,7 +225,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
return
|
||||
|
||||
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 = []
|
||||
|
||||
@@ -298,6 +311,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
print("green data print:", data, device, datetime.now())
|
||||
return None
|
||||
|
||||
# print('data=', list(data))
|
||||
# print('Ram:', data[62])
|
||||
|
||||
if (length >= 4000):
|
||||
flag_print = True
|
||||
print("green data: big length:", length)
|
||||
@@ -413,9 +429,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
|
||||
finally:
|
||||
# print("\n")
|
||||
self.pin_busy.output(True)
|
||||
# finally:
|
||||
# # print("\n")
|
||||
# self.pin_busy.output(True)
|
||||
|
||||
return bytes(rx)
|
||||
|
||||
@@ -441,6 +457,16 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
self._spi.send_byte(tx)
|
||||
|
||||
def test_ram(self, channel: int):
|
||||
spi_MOSI = [MEM_INS_WRITE, 0, 0, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
|
||||
self._spi.send_byte(spi_MOSI)
|
||||
print('device:', channel, 'spi_MOSI:',spi_MOSI)
|
||||
|
||||
spi_MISO = [0] * len(spi_MOSI)
|
||||
spi_MISO[0:3] = [MEM_INS_READ, 0, 0]
|
||||
spi_MISO = self._spi.send_byte(spi_MISO)
|
||||
print('device:', channel, 'spi_MISO:', spi_MISO)
|
||||
|
||||
class ExtMemManager:
|
||||
def __init__(self, ext_mem: MultiExtMemSpiInterface):
|
||||
self._ext_mem = ext_mem
|
||||
@@ -477,28 +503,31 @@ class ExtMemManager:
|
||||
|
||||
ret[channel] = tuple(r)
|
||||
|
||||
print('ret=', ret)
|
||||
return ret
|
||||
|
||||
@staticmethod
|
||||
def is_no_device(result: Tuple[Optional[int], Optional[int]]) -> bool:
|
||||
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]], channel: int) -> int:
|
||||
r1, r2 = result
|
||||
return (r1 is None or r2 is None) and (r1 is None or r1 == 0) and (r2 is None or r2 == 0)
|
||||
r1_check = False
|
||||
r2_check = False
|
||||
|
||||
@staticmethod
|
||||
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]]) -> int:
|
||||
r1, r2 = result
|
||||
if r1 is not None and r1 != 0:
|
||||
if (r1 & 0b11000001 == DEFAULT_REGISTER_VALUE & 0b11000001):
|
||||
r1_check = True
|
||||
print('device:', channel, 'ram0 ready')
|
||||
|
||||
if r2 is not None and r2 != 0:
|
||||
if (r2 & 0b11000001 == DEFAULT_REGISTER_VALUE & 0b11000001):
|
||||
r2_check = True
|
||||
print('device:', channel, 'ram1 ready')
|
||||
print('--------------------')
|
||||
|
||||
if r1 is None or r2 is None:
|
||||
if r1_check and r2_check:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
if r1 is not None and r1 > 0 and r1 != DEFAULT_REGISTER_VALUE:
|
||||
return 2
|
||||
|
||||
if r2 is not None and r2 > 0 and r2 != DEFAULT_REGISTER_VALUE:
|
||||
return 3
|
||||
|
||||
return 0
|
||||
|
||||
def get_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
||||
if result is None:
|
||||
result = self.get_ext_mem_register()
|
||||
@@ -506,12 +535,14 @@ class ExtMemManager:
|
||||
ret = []
|
||||
|
||||
for channel, result in enumerate(result):
|
||||
if self.is_no_device(result):
|
||||
continue
|
||||
|
||||
if self.is_memory_test_fail(result) != 0:
|
||||
if self.is_memory_test_fail(result, channel) != 0:
|
||||
continue
|
||||
|
||||
ret.append(channel)
|
||||
|
||||
# test ram
|
||||
# for channel in self._ext_mem.foreach():
|
||||
# if channel == 4 or channel == 5:
|
||||
# self._ext_mem.test_ram(channel)
|
||||
|
||||
return ret
|
||||
|
||||
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
|
||||
self._serial = serial.Serial(self._port,
|
||||
baudrate=self._baudrate,
|
||||
timeout=0,
|
||||
writeTimeout=0.01)
|
||||
writeTimeout=1)
|
||||
# deprecate function name which change at version 3.0
|
||||
self._serial.flushInput()
|
||||
self._serial.flushOutput()
|
||||
@@ -53,6 +53,8 @@ class UARTInterface(LowLevelHardwareInterface):
|
||||
:param data: raw byte instruction
|
||||
:raises SerialTimeoutException:
|
||||
"""
|
||||
data_hex = ''.join(format(i, '02X') for i in data)
|
||||
# print('send_byte: 0x{0}'.format(data_hex.upper()))
|
||||
self._serial.write(data)
|
||||
|
||||
def recv_byte(self, size: int) -> Optional[bytes]:
|
||||
|
||||
@@ -118,13 +118,13 @@ class Selector:
|
||||
self._p2.output(p[2])
|
||||
|
||||
# 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):
|
||||
# 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):
|
||||
# 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):
|
||||
# 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
|
||||
|
||||
|
||||
@@ -24,3 +24,11 @@ class Action():
|
||||
@property
|
||||
def condition(self):
|
||||
return self._condition
|
||||
|
||||
def as_json(self):
|
||||
return {
|
||||
'id': self._id,
|
||||
'type': self._type,
|
||||
'target': self._target,
|
||||
'condition': self._condition
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ class Condition():
|
||||
# print(operator, x, y)
|
||||
cases = {
|
||||
"equal": lambda a, b: a == b,
|
||||
"bigger": lambda a, b: a > b,
|
||||
"smaller": lambda a, b: a < b,
|
||||
"bigger": lambda a, b: a >= b,
|
||||
"smaller": lambda a, b: a <= b,
|
||||
}
|
||||
|
||||
return cases[operator](x, y)
|
||||
@@ -56,7 +56,8 @@ class Condition():
|
||||
return getattr(self, self.type)(**kwargs)
|
||||
|
||||
def absolute_time(self, **kwargs):
|
||||
now = int(time())
|
||||
# now = int(time())
|
||||
now = round(time(), 1)
|
||||
time_condition = round(self.datetime_to_timestamp(self.str_to_datetime(self._value)))
|
||||
|
||||
return self.compareWith(self.comparsion, now, time_condition)
|
||||
@@ -65,32 +66,80 @@ class Condition():
|
||||
project_start_time = kwargs['project_start_time']
|
||||
delay_time = kwargs['delay_time']
|
||||
|
||||
time_diff = int(time() - project_start_time - delay_time)
|
||||
return self.compareWith(self.comparsion, time_diff, int(self._value))
|
||||
# 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,kwargs['task_start_time'],kwargs['delay_time'])
|
||||
# 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 = int(time() - task_start_time - delay_time)
|
||||
# print('time_diff', time_diff)
|
||||
return self.compareWith(self.comparsion, time_diff, int(self._value))
|
||||
|
||||
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):
|
||||
print('device')
|
||||
|
||||
def previous_task_done(self, **kwargs):
|
||||
""" def previous_task_done(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
if running_task.status == 2 and self._active == False:
|
||||
self._active = True
|
||||
return True
|
||||
return False """
|
||||
|
||||
def previous_task_done(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
self_task = kwargs['self_task']
|
||||
# if running_task != None and self_task != None:
|
||||
# print('\nprevious_task_done: ', running_task.status, ' ', self._active)
|
||||
if running_task != self_task:
|
||||
if running_task == None:
|
||||
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):
|
||||
return datetime.strptime(time_str,'%Y-%m-%dT%H:%M')
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class 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:
|
||||
@@ -29,4 +30,8 @@ class Instruction():
|
||||
|
||||
@property
|
||||
def stop(self) -> list:
|
||||
return self._stop_instruction
|
||||
return self._stop_instruction
|
||||
|
||||
@property
|
||||
def idle(self) -> list:
|
||||
return self.idle_instruction
|
||||
@@ -1,6 +1,7 @@
|
||||
import sys
|
||||
import json
|
||||
import threading
|
||||
import logging
|
||||
|
||||
from time import time, sleep
|
||||
from datetime import datetime
|
||||
@@ -14,17 +15,20 @@ from .instruction import Instruction
|
||||
from biopro.device.manager import DeviceManager
|
||||
from biopro.text import *
|
||||
|
||||
from biopro.db.base import Session
|
||||
from biopro.db.collection import Collection
|
||||
|
||||
key_list = {
|
||||
'deviceList': 'device',
|
||||
}
|
||||
|
||||
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)
|
||||
self._project = project
|
||||
self._device_manager = device_manager
|
||||
self._mqtt_thread = mqttThread
|
||||
self._time_interval = 1
|
||||
self._time_interval = 0.1
|
||||
self._start_time = None
|
||||
self._end_time = None
|
||||
|
||||
@@ -33,7 +37,7 @@ class Project(threading.Thread):
|
||||
self._name = None
|
||||
self._desc = None
|
||||
self._device = None
|
||||
self._complete_device = []
|
||||
self._complete_device = {}
|
||||
self._status = 0
|
||||
|
||||
self._instruction_set = Instruction()
|
||||
@@ -41,16 +45,40 @@ class Project(threading.Thread):
|
||||
|
||||
self._task_manager = None
|
||||
|
||||
self._cycle = []
|
||||
|
||||
self._count = 1 #流水號
|
||||
|
||||
self.log_verbose = log_verbose
|
||||
self._logger = logging.getLogger('project')
|
||||
self._logger.setLevel('DEBUG')
|
||||
|
||||
self._formatter = logging.Formatter('[%(asctime)s.%(msecs)03d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
|
||||
self._formatter_with_nothing = logging.Formatter('%(message)s')
|
||||
|
||||
self.setup_project(project)
|
||||
self.setup_device(self._device)
|
||||
|
||||
|
||||
# create log file handler
|
||||
fh = logging.FileHandler(f'/home/pi/logger/project/{self.uuid}.log', mode="w")
|
||||
fh.setFormatter(self._formatter)
|
||||
self._logger.addHandler(fh)
|
||||
|
||||
default_name = 'admin'
|
||||
default_parent = {"folder": [1]}
|
||||
collection = Collection.find_collection(default_name, default_parent)
|
||||
parent = {"folder": [collection.id]}
|
||||
# create project folder
|
||||
collection = Collection.create_collection(self.name, parent)
|
||||
self.setup_collection(collection)
|
||||
|
||||
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'])
|
||||
self._task_manager = TaskManager(project['task'], project['cycle'])
|
||||
elif key == 'uuid':
|
||||
pass
|
||||
else:
|
||||
@@ -58,8 +86,13 @@ class Project(threading.Thread):
|
||||
|
||||
def setup_device(self, device_list):
|
||||
for device in device_list:
|
||||
complete_device = self._device_manager.get_device(device['connectDevice']['device_address'])
|
||||
self._complete_device.append(complete_device)
|
||||
mac_address = device_list[device]['pair']
|
||||
complete_device = self._device_manager.get_device(mac_address)
|
||||
complete_device.occupied_by_project = self._uuid
|
||||
self._complete_device[device] = complete_device
|
||||
|
||||
def setup_collection(self, collection):
|
||||
self._task_manager.create_collection(collection)
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
@@ -84,6 +117,14 @@ class Project(threading.Thread):
|
||||
@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
|
||||
|
||||
@property
|
||||
def desc(self) -> str:
|
||||
@@ -117,9 +158,28 @@ class Project(threading.Thread):
|
||||
def mqtt_thread(self):
|
||||
return self._mqtt_thread
|
||||
|
||||
@property
|
||||
def running_task(self):
|
||||
return self._task_manager.running_task
|
||||
|
||||
def get_device_parameter_set(self, device_address):
|
||||
parameter_set = self._task_manager.running_task.parameter_set
|
||||
return next((x for x in parameter_set if parameter_set[x]['target'] == device_address), None)
|
||||
|
||||
def get_cycle(self, task):
|
||||
for index, _cycle in enumerate(self.cycle):
|
||||
if task.uuid in _cycle['range']:
|
||||
return _cycle
|
||||
|
||||
def run(self):
|
||||
# project status change running (1)
|
||||
self._status = 1
|
||||
# save start time
|
||||
self._start_time = time()
|
||||
|
||||
# saving & broadcast message
|
||||
self._logger.info('Project ' + self.name + ' start')
|
||||
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 :
|
||||
@@ -130,47 +190,111 @@ class Project(threading.Thread):
|
||||
for task in check_list:
|
||||
if task != None:
|
||||
now = time()
|
||||
# print('round task', task.name)
|
||||
# print('running task', self._task_manager.running_task.name, self._task_manager.running_task.status)
|
||||
# if self._task_manager.prev_task != None:
|
||||
# print('previous_task', self._task_manager.prev_task.name, self._task_manager.prev_task.status)
|
||||
|
||||
match_condition_list = task.check_condition(
|
||||
project_start_time = self._start_time,
|
||||
delay_time = delay_time,
|
||||
running_task= self._task_manager.running_task,
|
||||
previous_task = self._task_manager.prev_task
|
||||
previous_task = self._task_manager.prev_task,
|
||||
self_task = task
|
||||
)
|
||||
# print('match_condition_list', match_condition_list)
|
||||
|
||||
for condition in match_condition_list:
|
||||
match_action_list = task.get_match_action(condition.id)
|
||||
print('match_action_list', match_action_list, match_action_list)
|
||||
for action in match_action_list:
|
||||
# print('match_action', action.type, action.target)
|
||||
if action.type == 'start' and task.status != 1:
|
||||
self._task_manager.set_running_task(task)
|
||||
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)
|
||||
cycle_info = self.get_cycle(task)
|
||||
if cycle_info['useID'] == False:
|
||||
self._logger.info(f'---------- Cycle {task.name} Round {cycle_info["count"]} -----------')
|
||||
if action.type == 'cycle' and condition.type == 'until_button_trigger':
|
||||
self._task_manager.running_task.stop()
|
||||
self._logger.info(f'---------- Cycle {cycle_info["id"]} Round {cycle_info["count"]} -----------')
|
||||
|
||||
device = self._complete_device[action.target]
|
||||
task_info = task.get_task_info(action)
|
||||
instruction_set = getattr(self._instruction_set, action.type, None)
|
||||
# print('instruction_set',instruction_set)
|
||||
|
||||
if instruction_set != None:
|
||||
for instruction in instruction_set:
|
||||
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
|
||||
threading.Thread(target=getattr(device, instruction['method'])(*args))
|
||||
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._logger.info(f'Task {str(self._task_manager.running_task.name)} start')
|
||||
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()
|
||||
# elif action.type == 'stop':
|
||||
# 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._logger.info(f'Device {device.mac_address_in_str} {action.type}')
|
||||
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 self.get_device_parameter_set(action.target) != None:
|
||||
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())
|
||||
if action.type == 'start':
|
||||
self._count += 1
|
||||
|
||||
delay_time += (time() - now)
|
||||
|
||||
# check task not running then stop
|
||||
if self.check_running_task_not_run() == True:
|
||||
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._logger.info(f'taskType {self._task_manager.running_task.name} {self._task_manager.running_task.type}')
|
||||
if self._task_manager.running_task.type == '':
|
||||
self._logger.info(f'Task {self._task_manager.running_task.name} 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._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()
|
||||
self.stop()
|
||||
|
||||
if self._time_interval - delay_time > 0:
|
||||
sleep(self._time_interval - delay_time)
|
||||
@@ -180,14 +304,19 @@ class Project(threading.Thread):
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
for device in self._complete_device:
|
||||
self._complete_device[device].occupied_by_project = None
|
||||
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._logger.info('Project ' + self.name + ' stop')
|
||||
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):
|
||||
for device in self._complete_device:
|
||||
self._complete_device[device].occupied_by_project = None
|
||||
self._status = 2
|
||||
self._end_time = time()
|
||||
self._stop_flag = True
|
||||
@@ -200,17 +329,43 @@ class Project(threading.Thread):
|
||||
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,
|
||||
@@ -219,6 +374,19 @@ class Project(threading.Thread):
|
||||
'status': self._status,
|
||||
'device': self._device,
|
||||
'task': self.task_list,
|
||||
'running_task': self._task_manager.running_task.as_json()
|
||||
'running_task': running_task,
|
||||
'cycle': self._cycle,
|
||||
'count': self._count,
|
||||
}
|
||||
return data
|
||||
|
||||
def info_pass_data_server(self):
|
||||
if self._task_manager.running_task is not None:
|
||||
running_task = self._task_manager.running_task.as_json()
|
||||
data = {
|
||||
'project': self._uuid,
|
||||
'task': running_task,
|
||||
'cycle': self._cycle,
|
||||
'serial_number': self._count,
|
||||
}
|
||||
return data
|
||||
|
||||
@@ -9,13 +9,14 @@ def json_stringify(o: Any) -> str:
|
||||
return _json_stringify(o, separators=(',', ':'))
|
||||
|
||||
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._mqtt_thread = mqtt_thread
|
||||
self._device_manager = device_manager
|
||||
self.log_verbose = log_verbose
|
||||
|
||||
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)
|
||||
return new_project
|
||||
|
||||
@@ -37,3 +38,11 @@ class ProjectManager():
|
||||
def stop_project(self, project):
|
||||
_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)
|
||||
|
||||
@@ -12,29 +12,39 @@ key_list = {
|
||||
class Task:
|
||||
def __init__(self, task):
|
||||
self._id = None
|
||||
self._uuid = None
|
||||
self._type = None
|
||||
self._name = None
|
||||
self._parent = None
|
||||
self._cycle = None
|
||||
self._cycle_count = 0
|
||||
self._cycle_next = None
|
||||
self._cycle_next_uuid = None
|
||||
self._device = None
|
||||
self._event = None
|
||||
self._trigger = None
|
||||
self._parameter_set = None
|
||||
self._condition = None
|
||||
self._action = None
|
||||
# -1: initial 0: start(idle), 1: running, 2: close(idle)
|
||||
# -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._record_list = []
|
||||
|
||||
# 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 load_task(self, task) -> None:
|
||||
@@ -74,6 +84,14 @@ class Task:
|
||||
@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):
|
||||
@@ -100,6 +118,31 @@ class Task:
|
||||
@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:
|
||||
@@ -177,6 +220,14 @@ class Task:
|
||||
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())
|
||||
|
||||
@@ -207,6 +258,10 @@ class Task:
|
||||
|
||||
def stop(self):
|
||||
self.status = 2
|
||||
|
||||
def reset(self):
|
||||
self.status = -1
|
||||
# self.status = 0
|
||||
|
||||
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)
|
||||
@@ -230,7 +285,7 @@ class Task:
|
||||
return {
|
||||
'device': action.target,
|
||||
'parameter': self.get_parameter_set_by_device(action.target),
|
||||
'file_name': self._name + '-' + str(action.target),
|
||||
'file_name': self._name,
|
||||
'parent': self.parent,
|
||||
'instruction': _type
|
||||
}
|
||||
@@ -240,7 +295,12 @@ class Task:
|
||||
'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,
|
||||
|
||||
@@ -5,6 +5,7 @@ from xml.dom.expatbuilder import parseString
|
||||
import paho.mqtt.client as mqtt
|
||||
from biopro.text import *
|
||||
from .task import Task
|
||||
from biopro.db.collection import Collection
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
@@ -12,11 +13,12 @@ def json_stringify(o: Any) -> str:
|
||||
return _json_stringify(o, separators=(',', ':'))
|
||||
|
||||
class TaskManager():
|
||||
def __init__(self, task_list):
|
||||
def __init__(self, task_list, cycle_list):
|
||||
self._task_list = []
|
||||
self._next_task = []
|
||||
self._prev_task = None
|
||||
self._running_task = None
|
||||
self._cycle_list = cycle_list
|
||||
|
||||
self.load_task_list(task_list)
|
||||
|
||||
@@ -44,6 +46,35 @@ class TaskManager():
|
||||
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_start(self, task):
|
||||
for index, cycle in enumerate(self._cycle_list):
|
||||
if cycle['range'][0] == task.uuid:
|
||||
return index
|
||||
|
||||
def check_task_is_cycle_end(self, task):
|
||||
for index, cycle in enumerate(self._cycle_list):
|
||||
if cycle['range'][1] == task.uuid:
|
||||
return index
|
||||
|
||||
def check_task_in_cycle(self, task_index):
|
||||
for index, cycle in enumerate(self._cycle_list):
|
||||
if self.get_index_by_uuid(cycle['range'][0]) <= task_index:
|
||||
if self.get_index_by_uuid(cycle['range'][1]) >= task_index:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def check_list(self):
|
||||
return [self._running_task, *self._next_task]
|
||||
@@ -57,7 +88,8 @@ class TaskManager():
|
||||
task = Task(task)
|
||||
self._task_list.append(task)
|
||||
|
||||
def set_running_task(self, task):
|
||||
# original version
|
||||
""" 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:
|
||||
@@ -80,9 +112,70 @@ class TaskManager():
|
||||
_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_start_index = self.check_task_is_cycle_start(task)
|
||||
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
|
||||
|
||||
if cycle_start_index != None:
|
||||
cycle = self._cycle_list[cycle_start_index]
|
||||
if int(cycle['count']) < int(cycle['max']):
|
||||
cycle['count'] += 1
|
||||
else:
|
||||
cycle['count'] = 1
|
||||
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
|
||||
def get_task(self, task_id):
|
||||
return self._task_list[task_id]
|
||||
|
||||
|
||||
def create_collection(self, parent):
|
||||
for index, task in enumerate(self._task_list):
|
||||
if self.check_task_in_cycle(index) == True:
|
||||
if task.type == '':
|
||||
collection = Collection.create_collection(task.name, {"folder": [parent.id]})
|
||||
task.parent = {"folder": [collection.id]}
|
||||
else:
|
||||
task.parent = {"folder": [parent.id]}
|
||||
@@ -118,7 +118,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
'_dirty', '_last_modify_time', '_file_size_cache',
|
||||
'_recording_file_ch', '_recording_sub_file', '_size',
|
||||
'_parameter', '_parent', '_recording_file_name', '_recording_sub_mini', '_recording_mini_ch',
|
||||
'_raw_serial_number', '_mini_serial_number', '_device_id')
|
||||
'_raw_serial_number', '_mini_serial_number', '_device_id', '_project_id')
|
||||
|
||||
def __init__(self, filepath: Union[str, Path], data_format: bytes = None, id_db = 0, database = None):
|
||||
if isinstance(filepath, str):
|
||||
@@ -153,6 +153,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
self._parent = ''
|
||||
self._recording_file_name = ''
|
||||
self._device_id = -1
|
||||
self._project_id = None
|
||||
|
||||
# recording parameter
|
||||
self._configuration = None
|
||||
@@ -297,6 +298,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
'uuid': str(self._file_uuid),
|
||||
'data_format': 'rec',
|
||||
'device': self._device,
|
||||
'project': self._project_id,
|
||||
}
|
||||
|
||||
if len(self._parent) > 0:
|
||||
@@ -462,7 +464,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def parameter(self) -> str:
|
||||
return self._parameter
|
||||
|
||||
@device.setter
|
||||
@parameter.setter
|
||||
def parameter(self, parameter):
|
||||
self._parameter = parameter
|
||||
return None
|
||||
@@ -471,7 +473,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def parent(self) -> str:
|
||||
return self._parent
|
||||
|
||||
@device.setter
|
||||
@parent.setter
|
||||
def parent(self, parent):
|
||||
self._parent = parent
|
||||
|
||||
@@ -479,7 +481,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def recording_file_name(self) -> str:
|
||||
return self._recording_file_name
|
||||
|
||||
@device.setter
|
||||
@recording_file_name.setter
|
||||
def recording_file_name(self, recording_file_name):
|
||||
self._recording_file_name = recording_file_name
|
||||
|
||||
@@ -492,6 +494,15 @@ class RecordingMetaFile(JsonSerialize):
|
||||
self._configuration = conf
|
||||
self._dirty = True
|
||||
return None
|
||||
|
||||
@property
|
||||
def project_id(self) -> int:
|
||||
return self._project_id
|
||||
|
||||
@project_id.setter
|
||||
def project_id(self, project: int):
|
||||
self._project_id = project
|
||||
return None
|
||||
|
||||
@property
|
||||
def channels(self) -> List[int]:
|
||||
@@ -1131,14 +1142,17 @@ class RecordingFileWriter:
|
||||
self._splitting_size = 0
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
# if self._recording_file is not None:
|
||||
# self._recording_file.close()
|
||||
# self._recording_file = None
|
||||
print('close1')
|
||||
def close(self, mqtt_thread):
|
||||
self._close = True
|
||||
if len(self._recording_file_dict) > 0:
|
||||
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:
|
||||
_data = ' '.join(self._data_db[ch])
|
||||
self._raw_save['data'][ch] = _data
|
||||
|
||||
@@ -4,7 +4,6 @@ from time import time, sleep
|
||||
from typing import Iterable
|
||||
from datetime import datetime
|
||||
import gc
|
||||
|
||||
import base64
|
||||
|
||||
from biopro.data import *
|
||||
@@ -27,7 +26,6 @@ from .mqtt import MqttDataMessageHandler, MqttThread
|
||||
from .database import DataBaseProcess
|
||||
from .recording import RecordingProcess
|
||||
from multiprocessing import Queue
|
||||
import queue
|
||||
|
||||
from json import loads as json_parse, dumps as _json_stringify
|
||||
import json
|
||||
@@ -65,7 +63,7 @@ class DataServer(SocketServer, DataAPI):
|
||||
"""
|
||||
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)
|
||||
|
||||
@@ -117,6 +115,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
self.database_process = DataBaseProcess('data_server', self.log_verbose, self._queue_db, self._queue_ds_dict, self._queue_msg)
|
||||
self.database_process.start()
|
||||
|
||||
# self._no_data_total_duration = 0
|
||||
# self._recv_memory_cost_time = 0
|
||||
|
||||
@logging_info
|
||||
def setup(self):
|
||||
self._available_channel.clear()
|
||||
@@ -314,7 +315,8 @@ class DataServer(SocketServer, DataAPI):
|
||||
def update_device_configuration(self,
|
||||
device: str,
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
# meta file
|
||||
|
||||
device_id = -1
|
||||
@@ -342,6 +344,8 @@ class DataServer(SocketServer, DataAPI):
|
||||
_parent = json_stringify(_device['parent'])
|
||||
_recording_file_name = _device['recording_file_name']
|
||||
mac_address = json.loads(device)['device_address']
|
||||
device_id = _device['device_id']
|
||||
|
||||
del _device['configuration']
|
||||
del _device['parent']
|
||||
del _device['recording_file_name']
|
||||
@@ -351,13 +355,22 @@ class DataServer(SocketServer, DataAPI):
|
||||
# meta_file.parameter = _parameter
|
||||
# meta_file.parent = _parent
|
||||
# meta_file.recording_file_name = _recording_file_name
|
||||
device_id = int(json.loads(device)['device_id'])
|
||||
|
||||
if device_id < 0:
|
||||
raise ValueError('illegal device ID : ' + str(device_id))
|
||||
|
||||
self.log_verbose('device ID', device_id)
|
||||
|
||||
# project binding meta file
|
||||
# project_id = None
|
||||
# _project = None
|
||||
# if project_info != None:
|
||||
# _project = json.loads(project_info)
|
||||
# self.database_process.put_queue(['project_insert', device_id, _project])
|
||||
# result = self._queue_ds_dict[int(device_id)].get()
|
||||
# if result[0] == 'project_id':
|
||||
project_id = project_info
|
||||
|
||||
# while len(self._configurations) <= device_id:
|
||||
# self._configurationsappend(None)
|
||||
|
||||
@@ -377,8 +390,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
else:
|
||||
data_format = data_format.name
|
||||
|
||||
# self.log_verbose('device data format', data_format)
|
||||
|
||||
self.log_verbose('device meta file', meta_file)
|
||||
|
||||
# data runtime
|
||||
@@ -403,15 +414,15 @@ class DataServer(SocketServer, DataAPI):
|
||||
c.shutdown()
|
||||
c.join()
|
||||
self._spi.set_wait_flag(c._device, True)
|
||||
|
||||
data_runtime_process = RecordingProcess('data_server', self.log_verbose, device_id,
|
||||
Queue(), self._queue_ds_dict[int(device_id)], self._queue_msg, meta_file,
|
||||
json_stringify(_device), _parameter, _parent, _recording_file_name,
|
||||
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
|
||||
database = self.database_process )
|
||||
# data_runtime_process.start()
|
||||
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
|
||||
project_id = project_id,
|
||||
database = self.database_process)
|
||||
|
||||
# check channel
|
||||
|
||||
if isinstance(data_runtime_process, RecordingProcess) and device_id not in self._available_channel:
|
||||
raise RuntimeError('set device configuration on un-available channel', device_id)
|
||||
|
||||
@@ -643,6 +654,7 @@ class DataServer(SocketServer, DataAPI):
|
||||
def whether_to_record(self, device):
|
||||
# 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:
|
||||
# print(self._configurations.keys(), ',', device, datetime.now())
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -651,6 +663,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
ret = False
|
||||
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():
|
||||
spi_data = sync.recv_memory(device)
|
||||
signal = sync.get_pin_mem_req()
|
||||
@@ -659,14 +674,27 @@ class DataServer(SocketServer, DataAPI):
|
||||
|
||||
else:
|
||||
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 self._configurations[device].queue_flag:
|
||||
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:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
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
|
||||
|
||||
@@ -686,6 +714,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True)
|
||||
|
||||
return True
|
||||
|
||||
def show_data(self, device):
|
||||
self._configurations[device].put_rec_queue('show_data')
|
||||
|
||||
class DataRuntime(metaclass=abc.ABCMeta):
|
||||
__slots__ = ('_server', '_device', '_meta_file', '_data_format',
|
||||
|
||||
@@ -222,7 +222,8 @@ class DataBaseProcess(Process):
|
||||
|
||||
try:
|
||||
sql_cursor.execute(sql_str, sql_set)
|
||||
except:
|
||||
except BaseException as e:
|
||||
print('meta create error', e)
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
self._queue_error.put(device_id)
|
||||
@@ -249,7 +250,8 @@ class DataBaseProcess(Process):
|
||||
|
||||
try:
|
||||
sql_cursor.execute(sql_str, sql_set)
|
||||
except:
|
||||
except BaseException as e:
|
||||
print('meta update error', e)
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
self._queue_error.put(device_id)
|
||||
@@ -550,4 +552,33 @@ class DataBaseProcess(Process):
|
||||
except psycopg2.Error as e:
|
||||
print('e', e)
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def project_insert(self, device_id, _data):
|
||||
sql_str = 'INSERT INTO "public"."project_metas" ('
|
||||
sql_set = []
|
||||
for item in _data.keys():
|
||||
sql_str = sql_str + str(item) + ', '
|
||||
if isinstance(_data[item], dict) or isinstance(_data[item], list):
|
||||
sql_set.append(json_stringify(_data[item]))
|
||||
else:
|
||||
sql_set.append(_data[item])
|
||||
|
||||
sql_str = sql_str[0:-2] + ') VALUES ('
|
||||
for item in _data.keys():
|
||||
sql_str = sql_str + '%s, '
|
||||
|
||||
sql_str = sql_str[0:-2] + ') RETURNING id'
|
||||
sql_cursor = self._psql_conn.cursor()
|
||||
|
||||
try:
|
||||
sql_cursor.execute(sql_str, sql_set)
|
||||
except BaseException as e:
|
||||
print('insert error', e)
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
self._queue_error.put()
|
||||
finally:
|
||||
self._queue_ds[int(device_id)].put(['project_id', int(sql_cursor.fetchone()[0])])
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
|
||||
+121
-32
@@ -1,6 +1,9 @@
|
||||
from time import sleep
|
||||
from typing import Iterable
|
||||
from datetime import datetime
|
||||
import json
|
||||
import threading
|
||||
from time import time
|
||||
|
||||
import biopro.impl.vcgencmd as vcg
|
||||
from biopro.data import DataServerOptions, DataAPI
|
||||
@@ -31,8 +34,11 @@ from biopro.api.auth import AuthAPI
|
||||
from biopro.api.controller import ControllerAPI
|
||||
from biopro.api.device import DeviceAPI
|
||||
from biopro.project.project_manager import ProjectManager
|
||||
### do not import Websocket mode
|
||||
###from .websocket import WebsocketThread
|
||||
from biopro.db.base import Base, Session, engine
|
||||
from biopro.db.project_report import ProjectReport
|
||||
from biopro.db.project_meta import MetaProjectInfo
|
||||
from biopro.db.device import Device
|
||||
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
@@ -105,7 +111,7 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
# device detect
|
||||
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._project_manager = ProjectManager(self.device_manager, self.mqtt_thread, self.log_verbose)
|
||||
|
||||
if not c.flag_disable_led_control:
|
||||
self.led_thread.set_state(LED.COLOR_RED)
|
||||
@@ -117,8 +123,8 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
self.ups_thread = UPSDetectThread(self, c.flag_ups_wait_time)
|
||||
|
||||
# user session
|
||||
self._session = {}
|
||||
self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
|
||||
# self._session = {}
|
||||
# self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
|
||||
|
||||
# indicate those device together
|
||||
self._device_instruction_group = None
|
||||
@@ -129,6 +135,10 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
# _api request build
|
||||
self._api = ApiRequests()
|
||||
|
||||
# sqlalchemy
|
||||
Base.metadata.create_all(engine)
|
||||
self._session = Session()
|
||||
|
||||
# init method
|
||||
|
||||
def _init_file_manager(self, option: ControlServerOptions) -> FileManager:
|
||||
@@ -819,12 +829,21 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def device_battery(self) -> List[int]:
|
||||
device_list = self.device_manager.list_device()
|
||||
if len(device_list) > 0:
|
||||
battery_list = list(map(lambda x: self.device_manager.get_device(x).battery, device_list))
|
||||
|
||||
return battery_list
|
||||
def device_battery(self, device:int) -> List[int]:
|
||||
try:
|
||||
battery = {}
|
||||
if device == 'all':
|
||||
device_list = self.device_manager.list_device()
|
||||
if len(device_list) > 0:
|
||||
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
|
||||
}
|
||||
except AttributeError as e:
|
||||
print('device_battery', device, 'not found', e)
|
||||
return battery
|
||||
|
||||
@logging_info
|
||||
def device_parent(self, device: int, content: Optional[str] = None) -> List[int]:
|
||||
@@ -846,20 +865,32 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
@logging_info
|
||||
def device_update_calibration(self, device: int) -> Union[bool, str]:
|
||||
connect_device = self.device_manager.get_device(device)
|
||||
mac_address = connect_device.mac_address
|
||||
|
||||
if connect_device == None:
|
||||
return
|
||||
mac_address = address_str(connect_device.mac_address)
|
||||
device = Device.get_device({"mac_address": mac_address})
|
||||
try:
|
||||
if connect_device.library.name.startswith('Neulive3.'):
|
||||
connect_device.calibration_info('NeuliveThreeOne')
|
||||
elif connect_device.library.name.startswith('Neulive'):
|
||||
connect_device.calibration_info('TDC4VC')
|
||||
elif connect_device.library.name.startswith('EliteEIS'):
|
||||
connect_device.calibration_info('EISZeroOne')
|
||||
|
||||
if connect_device.library.name.startswith('Elite_EIS'):
|
||||
# update calibration version
|
||||
connect_device._device.update_cali_version()
|
||||
# check if is first time or calibration version is different
|
||||
if connect_device._device._cali_version == -1 or (device.calibration_version != connect_device._device._cali_version):
|
||||
# get calibration info from device
|
||||
connect_device.calibration_info('EISZeroOne')
|
||||
# update_calibration_info
|
||||
Device.update_device(
|
||||
{ "mac_address": mac_address },
|
||||
{
|
||||
'calibration': connect_device.calibration ,
|
||||
'calibration_version': connect_device._device._cali_version
|
||||
}
|
||||
)
|
||||
else:
|
||||
connect_device._device._coeff = device.calibration
|
||||
except BaseException as e:
|
||||
# reset device info in db
|
||||
DeviceAPI.updateByMac(
|
||||
address_str(mac_address),
|
||||
mac_address,
|
||||
{
|
||||
'connect_id': -1,
|
||||
'connect_status': 'idle',
|
||||
@@ -871,14 +902,6 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
print(e)
|
||||
return False
|
||||
else:
|
||||
# update_calibration_info
|
||||
DeviceAPI.updateByMac(
|
||||
address_str(mac_address),
|
||||
{
|
||||
'calibration': str(connect_device.calibration)
|
||||
}
|
||||
)
|
||||
# DeviceAPI.updateByAttrs('connect_status', 'update', {"connect_status": 'connect'})
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
@@ -1016,6 +1039,16 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
def run_project(self, project) -> bool:
|
||||
if project is not None:
|
||||
project = self._project_manager.create(project)
|
||||
with self._session as session:
|
||||
project_report = ProjectReport(
|
||||
name = project.name,
|
||||
uuid = project.uuid,
|
||||
cycle = project.cycle,
|
||||
task = project.task_list,
|
||||
device = project.device
|
||||
)
|
||||
session.add(project_report)
|
||||
session.commit()
|
||||
self._project_manager.run_project(project)
|
||||
return project.as_json()
|
||||
|
||||
@@ -1024,6 +1057,18 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
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
|
||||
def get_running_project(self) -> bool:
|
||||
@@ -1045,6 +1090,38 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE:
|
||||
return True
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_IDLE:
|
||||
device.status = 1
|
||||
return True
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_COUNTDOWN:
|
||||
if value == 'PULSE_OUTPUT':
|
||||
continue_mode = device.get_parameter('CONTINUE_MODE')
|
||||
if continue_mode == 0:
|
||||
stop_time = device.get_parameter('STOP_TIME')
|
||||
# Function to send the instruction
|
||||
def send_instruction():
|
||||
device.call_instruction('deactive_electrode')
|
||||
|
||||
# Function to wait for 30 seconds and then execute the instruction
|
||||
def delayed_execution(stop_time):
|
||||
sleep(stop_time)
|
||||
send_instruction()
|
||||
device.set_parameter('ACTIVATE_ELECTRODE', 0)
|
||||
self.mqtt_thread.broadcast_command('device_refresh')
|
||||
|
||||
# Create a thread for the delayed execution
|
||||
thread = threading.Thread(target=delayed_execution, args=(stop_time,))
|
||||
|
||||
# Start the thread
|
||||
thread.start()
|
||||
|
||||
# Main program continues without waiting for the thread
|
||||
# print("Main program continues...")
|
||||
# print('COUNTDOWN!!!', device, oper, value)
|
||||
# print(device.get_parameter(value), device.get_parameter_value(value))
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
@@ -1059,6 +1136,8 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
self.log_verbose('update data format', value)
|
||||
|
||||
client = self.data_server.client()
|
||||
project = None
|
||||
project_meta_id = None
|
||||
if client is not None:
|
||||
info = self.file_manager.use(device)
|
||||
|
||||
@@ -1069,9 +1148,13 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
filename = self._file_save_cache.get(device.device_id, self.TEMP_FILENAME_EXPR)
|
||||
filename = format_filename(filename, device)
|
||||
info = self.file_manager.save(device, filename)
|
||||
|
||||
|
||||
if device.occupied_by_project != None:
|
||||
project = self.project_manager.get(device.occupied_by_project).info_pass_data_server()
|
||||
project_meta_id = MetaProjectInfo.create_project_meta(project)
|
||||
|
||||
with client:
|
||||
client.update_device_configuration(device, info.meta_file, value)
|
||||
client.update_device_configuration(device, info.meta_file, value, project_meta_id)
|
||||
|
||||
def _device_set_disable_cache(self, device: CompletedDevice, disable):
|
||||
if disable:
|
||||
@@ -1105,7 +1188,6 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
filename = format_filename(self.TEMP_FILENAME_EXPR, device)
|
||||
info = self.file_manager.save(device, filename)
|
||||
client.update_device_configuration(device, info.meta_file, RawDataDecoder())
|
||||
|
||||
if self._device_instruction_group is None:
|
||||
client.start_sync(device)
|
||||
|
||||
@@ -1339,6 +1421,13 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
def _hardware_send_test_set(self, options: Dict[str, str]) -> bool:
|
||||
# TODO write options files
|
||||
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):
|
||||
def __init__(self):
|
||||
|
||||
@@ -44,7 +44,9 @@ class RecordingProcess(Process):
|
||||
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,
|
||||
mqtt_ip, mqtt_port,
|
||||
name = 'Recording-Process', database = None):
|
||||
name = 'Recording-Process',
|
||||
project_id = None,
|
||||
database = None):
|
||||
super(RecordingProcess, self).__init__(name = name)
|
||||
|
||||
self._database = database
|
||||
@@ -57,6 +59,7 @@ class RecordingProcess(Process):
|
||||
self._meta_file._parent = parent
|
||||
self._meta_file._recording_file_name = recording_file_name
|
||||
self._meta_file._device_id = device_id
|
||||
self._meta_file._project_id = project_id
|
||||
print(self._meta_file._device, self._meta_file._parameter, self._meta_file._parent, self._meta_file._filepath)
|
||||
self._meta_file.write(self._database)
|
||||
|
||||
@@ -155,9 +158,6 @@ class RecordingProcess(Process):
|
||||
elif isinstance(decoder, EISZeroOneDataDecoder):
|
||||
# get amp_gain from meta file
|
||||
decoder._mode = self._meta_file.configuration.get_parameter('MODE')
|
||||
decoder._ac_amp = self._meta_file.configuration.get_parameter('AC_AMP')
|
||||
decoder._freq_start = self._meta_file.configuration.get_parameter('FREQ_START')
|
||||
decoder._freq_stop = self._meta_file.configuration.get_parameter('FREQ_STOP')
|
||||
|
||||
return decoder
|
||||
|
||||
@@ -185,6 +185,8 @@ class RecordingProcess(Process):
|
||||
self.final_write()
|
||||
self.is_closed = True
|
||||
return False
|
||||
elif q == 'show_data':
|
||||
self._decoder._show_data = not self._decoder._show_data
|
||||
else:
|
||||
self.rec_update()
|
||||
self.sync_data(q)
|
||||
@@ -229,25 +231,6 @@ class RecordingProcess(Process):
|
||||
# except:
|
||||
# pass
|
||||
|
||||
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)
|
||||
|
||||
if result is not None:
|
||||
##
|
||||
if len(self._mqtt_send_data_ch_level) == 0:
|
||||
@@ -264,9 +247,27 @@ class RecordingProcess(Process):
|
||||
self._writer.channels_update(ret[0].channels())
|
||||
self._writer.write(ret, self._mqtt_send_data_ch_level)
|
||||
# print('write time: ', time() - ctime1)
|
||||
|
||||
# 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 data
|
||||
return
|
||||
@@ -357,7 +358,8 @@ class RecordingProcess(Process):
|
||||
if colum_total == 1:
|
||||
print('this ram data < 3 records, colum_total = ', colum_total)
|
||||
print('raw_data[0]', list(raw_data[0]))
|
||||
return save
|
||||
save = True
|
||||
# return save
|
||||
|
||||
elif colum_total == 2:
|
||||
print('this ram data < 3 records, colum_total = ', colum_total)
|
||||
@@ -606,7 +608,7 @@ class RecordingProcess(Process):
|
||||
|
||||
def final_write(self):
|
||||
if self._writer is not None:
|
||||
return self._writer.close()
|
||||
return self._writer.close(self._mqtt_send_data_ch_level)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
@@ -93,13 +93,15 @@ class SocketClient(metaclass=abc.ABCMeta):
|
||||
if self._socket is None:
|
||||
try:
|
||||
self._socket = Socket(AF_UNIX, SOCK_STREAM)
|
||||
self._socket.settimeout(1)
|
||||
self._socket.settimeout(5)
|
||||
self._socket.connect(self._socket_file)
|
||||
except FileNotFoundError as e:
|
||||
raise RuntimeError('server not available') from e
|
||||
except Exception as e:
|
||||
print('open_socket error:', e)
|
||||
# except FileNotFoundError as e:
|
||||
# raise RuntimeError('server not available') from e
|
||||
|
||||
except ConnectionRefusedError as e:
|
||||
raise RuntimeError('server crash') from e
|
||||
# except ConnectionRefusedError as e:
|
||||
# raise RuntimeError('server crash') from e
|
||||
|
||||
def close_socket(self):
|
||||
if self._socket is not None:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,343 @@
|
||||
{
|
||||
"name": "CPG",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite-CPG.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 8,
|
||||
"major_version_number": 0,
|
||||
"minor_version_number": 1
|
||||
},
|
||||
"constant": {
|
||||
"TIME_MAX": 100000,
|
||||
"VOLT_MAX": 65536,
|
||||
"Const_Current_Range": 1500001,
|
||||
"BLE_WRITE_MAX": 255
|
||||
},
|
||||
"parameters": {
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"FREQUENCY": {
|
||||
"description": "FREQUENCY",
|
||||
"record_meta": true,
|
||||
"initial": [80, 0],
|
||||
"domain": {
|
||||
"list": [1000000]
|
||||
}
|
||||
},
|
||||
"AMPLITUDE": {
|
||||
"description": "AMPLITUDE",
|
||||
"record_meta": true,
|
||||
"initial": [1, 1],
|
||||
"domain": {
|
||||
"list": "float"
|
||||
}
|
||||
},
|
||||
"PULSE_WIDTH": {
|
||||
"description": "PULSE_WIDTH",
|
||||
"record_meta": true,
|
||||
"initial": [250, 250],
|
||||
"domain": {
|
||||
"list": [1000000]
|
||||
}
|
||||
},
|
||||
"PATTERN_MODE": {
|
||||
"description": "SELECT_ELECTRODE",
|
||||
"record_meta": true,
|
||||
"initial": [1, 0],
|
||||
"domain": {
|
||||
"list": "float"
|
||||
}
|
||||
},
|
||||
"CONTINUE_MODE": {
|
||||
"description": "CONTINUE_MODE",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [2],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"STOP_TIME": {
|
||||
"description": "STOP_TIME",
|
||||
"record_meta": true,
|
||||
"initial": 30,
|
||||
"domain": [1000000],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"ELECTRODE_SELECTOR": {
|
||||
"description": "ELECTRODE_SELECTOR",
|
||||
"record_meta": true,
|
||||
"initial": [true,false,true,false],
|
||||
"domain": {
|
||||
"list": [2]
|
||||
}
|
||||
},
|
||||
"WORKING_ELECTRODE": {
|
||||
"description": "WORKING_ELECTRODE",
|
||||
"record_meta": true,
|
||||
"initial": [0, 0, 0, 0],
|
||||
"domain": {
|
||||
"list": "float"
|
||||
}
|
||||
},
|
||||
"PATTERN_SELECTOR": {
|
||||
"description": "PATTERN_SELECTOR",
|
||||
"record_meta": true,
|
||||
"initial": [0, 0, 1, 1],
|
||||
"domain": {
|
||||
"list": "float"
|
||||
}
|
||||
},
|
||||
"ACTIVATE_ELECTRODE": {
|
||||
"description": "PATTERN_SELECTOR",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": "float"
|
||||
},
|
||||
|
||||
"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,
|
||||
"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,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"Electrical stimulation",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"TIME_UNIT": {
|
||||
"description": "Duration unit",
|
||||
"initial": 2,
|
||||
"value": [
|
||||
"h",
|
||||
"m",
|
||||
"s",
|
||||
"ms"
|
||||
]
|
||||
},
|
||||
"TIME_DURATION": {
|
||||
"description": "Run duration",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
"TIME_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
"output": [
|
||||
"active_electrode",
|
||||
"_countdown('PULSE_OUTPUT')"
|
||||
],
|
||||
"active_electrode": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"ch0": "ELECTRODE_SELECTOR[0]",
|
||||
"ch1": "ELECTRODE_SELECTOR[1]",
|
||||
"ch2": "ELECTRODE_SELECTOR[2]",
|
||||
"ch3": "ELECTRODE_SELECTOR[3]",
|
||||
"Amp1": {
|
||||
"expression": "PATTERN_SELECTOR[0]",
|
||||
"when": {
|
||||
"0": "AMPLITUDE[0]",
|
||||
"1": "AMPLITUDE[1]"
|
||||
}
|
||||
},
|
||||
"Freq1": {
|
||||
"expression": "PATTERN_SELECTOR[0]",
|
||||
"when": {
|
||||
"0": "FREQUENCY[0]",
|
||||
"1": "FREQUENCY[1]"
|
||||
}
|
||||
},
|
||||
"Pulse1": {
|
||||
"expression": "PATTERN_SELECTOR[0]",
|
||||
"when": {
|
||||
"0": "PULSE_WIDTH[0]",
|
||||
"1": "PULSE_WIDTH[1]"
|
||||
}
|
||||
},
|
||||
"Amp2": {
|
||||
"expression": "PATTERN_SELECTOR[2]",
|
||||
"when": {
|
||||
"0": "AMPLITUDE[0]",
|
||||
"1": "AMPLITUDE[1]"
|
||||
}
|
||||
},
|
||||
"Freq2": {
|
||||
"expression": "PATTERN_SELECTOR[2]",
|
||||
"when": {
|
||||
"0": "FREQUENCY[0]",
|
||||
"1": "FREQUENCY[1]"
|
||||
}
|
||||
},
|
||||
"Pulse2": {
|
||||
"expression": "PATTERN_SELECTOR[2]",
|
||||
"when": {
|
||||
"0": "PULSE_WIDTH[0]",
|
||||
"1": "PULSE_WIDTH[1]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": [
|
||||
"1XFF;1X02;1XA0;",
|
||||
"1bch0;1bch1;6b000000;",
|
||||
"4BAmp1;4BPulse1;4BFreq1;",
|
||||
"2b00;1bch2;1bch3;4b0000;",
|
||||
"4BAmp2;4BPulse2;4BFreq2;",
|
||||
"4BSTOP_TIME;",
|
||||
"1bch0;1bch1;1bch2;1bch3;4b0000;"
|
||||
]
|
||||
},
|
||||
"deactive_electrode": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"ch0": "ELECTRODE_SELECTOR[0]",
|
||||
"ch1": "ELECTRODE_SELECTOR[1]",
|
||||
"ch2": "ELECTRODE_SELECTOR[2]",
|
||||
"ch3": "ELECTRODE_SELECTOR[3]"
|
||||
},
|
||||
"data": [
|
||||
"1XFF;1X02;1XA1;",
|
||||
"1bch0;1bch1;1bch2;1bch3;4b0000;"
|
||||
]
|
||||
},
|
||||
"resume_electrode_0": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X06;4b1000;4b0000;"
|
||||
]
|
||||
},
|
||||
"resume_electrode_1": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X06;4b0100;4b0000;"
|
||||
]
|
||||
},
|
||||
"resume_electrode_2": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X06;4b0010;4b0000;"
|
||||
]
|
||||
},
|
||||
"resume_electrode_3": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X06;4b0001;4b0000;"
|
||||
]
|
||||
},
|
||||
"suspend_electrode_0": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X05;4b1000;4b0000;"
|
||||
]
|
||||
},
|
||||
"suspend_electrode_1": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X05;4b0100;4b0000;"
|
||||
]
|
||||
},
|
||||
"suspend_electrode_2": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X05;4b0010;4b0000;"
|
||||
]
|
||||
},
|
||||
"suspend_electrode_3": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X02;1X05;4b0001;4b0000;"
|
||||
]
|
||||
},
|
||||
"idle": [
|
||||
"_idle()"
|
||||
],
|
||||
"data_format": [
|
||||
"_data_format('I4V4Z4T4')",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "_disable_cache(True)",
|
||||
"1": "_disable_cache(True)",
|
||||
"*": "_disable_cache(False)"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"ble_write": {
|
||||
"type": "ALL",
|
||||
"data": [
|
||||
"255X>BLE_WRITE;"
|
||||
]
|
||||
},
|
||||
"dev_version": [
|
||||
"CIS_VERSION",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"dev_battery": [
|
||||
"CIS_VOLT",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"set_para_DAC_VOLT": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE2;X01;2B>DAC_VOLT"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+164
-70
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "EliteZM15",
|
||||
"name": "Elite_BAT_0.1",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 2,
|
||||
"minor_product_number": 3,
|
||||
"major_version_number": 1,
|
||||
"minor_version_number": 6
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
"TIME_MAX": 100000,
|
||||
@@ -114,6 +114,20 @@
|
||||
"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": {
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
@@ -139,11 +153,8 @@
|
||||
"DPV_pulse_option": {
|
||||
"description": "Invert of pulse option",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
"domain": "bool",
|
||||
"initial": false
|
||||
},
|
||||
"DPV_mode": {
|
||||
"description": "AUTO: 0 / ADVANCED: 1/ ENGINEERING: 2",
|
||||
@@ -158,11 +169,24 @@
|
||||
"DPV_engineering_enable": {
|
||||
"description": "Engineering mode switch",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
"domain": "bool",
|
||||
"initial": false
|
||||
},
|
||||
"V_initial": {
|
||||
"description": "Pulse Mode Segment Voltage",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
50000,
|
||||
25000,
|
||||
25000,
|
||||
25000
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
50001
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"V_initial_0": {
|
||||
"description": "Pulse Mode Segment Voltage 0",
|
||||
@@ -208,6 +232,22 @@
|
||||
"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": {
|
||||
"description": "Pulse Mode Segment Duration 0",
|
||||
"record_meta": true,
|
||||
@@ -252,6 +292,36 @@
|
||||
"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": {
|
||||
"description": "Pulse Mode Current Recording Period Start",
|
||||
"record_meta": true,
|
||||
@@ -340,6 +410,40 @@
|
||||
"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": {
|
||||
"description": "Pulse Mode Segment UI Order 0, value: segment ID + 1",
|
||||
"record_meta": true,
|
||||
@@ -676,7 +780,7 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_VSCAN": {
|
||||
"CA_VOLT": {
|
||||
"description": "Voltage of VScan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
@@ -1099,7 +1203,7 @@
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X07;",
|
||||
"X0C;",
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
@@ -1197,7 +1301,7 @@
|
||||
"curve_const_vscan": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_VSCAN",
|
||||
"va": "CA_VOLT",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1230,39 +1334,39 @@
|
||||
},
|
||||
"curve_pulse_sensing": [
|
||||
{
|
||||
"expression": "segment_ui_order_0",
|
||||
"expression": "segment_ui_order[0]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_1",
|
||||
"expression": "segment_ui_order[1]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_2",
|
||||
"expression": "segment_ui_order[2]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_3",
|
||||
"expression": "segment_ui_order[3]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
"pul_sen_start"
|
||||
@@ -1286,11 +1390,11 @@
|
||||
"pul_sen_segment_0": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_0",
|
||||
"vb": "t_pulse_0",
|
||||
"vc": "CURR_REC_START_0",
|
||||
"vd": "CURR_REC_END_0",
|
||||
"ve": "segment_order_0 - 1",
|
||||
"va": "V_initial[0]",
|
||||
"vb": "t_pulse[0]",
|
||||
"vc": "CURR_REC[0][0]",
|
||||
"vd": "CURR_REC[0][1]",
|
||||
"ve": "segment_order.index(segment_order[0])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1306,11 +1410,11 @@
|
||||
"pul_sen_segment_1": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_1",
|
||||
"vb": "t_pulse_1",
|
||||
"vc": "CURR_REC_START_1",
|
||||
"vd": "CURR_REC_END_1",
|
||||
"ve": "segment_order_1 - 1",
|
||||
"va": "V_initial[1]",
|
||||
"vb": "t_pulse[1]",
|
||||
"vc": "CURR_REC[1][0]",
|
||||
"vd": "CURR_REC[1][1]",
|
||||
"ve": "segment_order.index(segment_order[1])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1326,11 +1430,11 @@
|
||||
"pul_sen_segment_2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_2",
|
||||
"vb": "t_pulse_2",
|
||||
"vc": "CURR_REC_START_2",
|
||||
"vd": "CURR_REC_END_2",
|
||||
"ve": "segment_order_2 - 1",
|
||||
"va": "V_initial[2]",
|
||||
"vb": "t_pulse[2]",
|
||||
"vc": "CURR_REC[2][0]",
|
||||
"vd": "CURR_REC[2][1]",
|
||||
"ve": "segment_order.index(segment_order[2])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1346,11 +1450,11 @@
|
||||
"pul_sen_segment_3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_3",
|
||||
"vb": "t_pulse_3",
|
||||
"vc": "CURR_REC_START_3",
|
||||
"vd": "CURR_REC_END_3",
|
||||
"ve": "segment_order_3 - 1",
|
||||
"va": "V_initial[3]",
|
||||
"vb": "t_pulse[3]",
|
||||
"vc": "CURR_REC[3][0]",
|
||||
"vd": "CURR_REC[3][1]",
|
||||
"ve": "segment_order.index(segment_order[3])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1411,8 +1515,8 @@
|
||||
"parameter": {
|
||||
"va": "DPV_step_time",
|
||||
"vb": "DPV_notify_rate",
|
||||
"vc": "DPV_curr_rec_min",
|
||||
"vd": "DPV_curr_rec_max"
|
||||
"vc": "DPV_curr_rec[0]",
|
||||
"vd": "DPV_curr_rec[1]"
|
||||
},
|
||||
"data": [
|
||||
"1X0E;",
|
||||
@@ -1475,8 +1579,8 @@
|
||||
"parameter": {
|
||||
"va": "DPV_step_time",
|
||||
"vb": "DPV_notify_rate",
|
||||
"vc": "DPV_curr_rec_min",
|
||||
"vd": "DPV_curr_rec_max"
|
||||
"vc": "DPV_curr_rec[0]",
|
||||
"vd": "DPV_curr_rec[1]"
|
||||
},
|
||||
"data": [
|
||||
"1X10;",
|
||||
@@ -1529,16 +1633,6 @@
|
||||
"dpv_engineering_mode_advanced": [
|
||||
"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_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
File diff suppressed because it is too large
Load Diff
+1
-9
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "EliteZM02",
|
||||
"name": "Elite_EDC_1.4",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite.*",
|
||||
@@ -492,14 +492,6 @@
|
||||
"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": {
|
||||
"type": "RIS",
|
||||
"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
File diff suppressed because it is too large
Load Diff
+375
-166
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "EliteEIS",
|
||||
"name": "Elite_EIS_1.0",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite.*",
|
||||
@@ -9,7 +9,7 @@
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
"FREQ_MAX": 4294967296,
|
||||
"FREQ_MAX": 13333334,
|
||||
"VOLT_MAX": 65536,
|
||||
"BLE_WRITE_MAX": 255,
|
||||
"TIME_MAX": 100000
|
||||
@@ -26,17 +26,44 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CHANNEL": {
|
||||
"derzteription": "record channels",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
"HIGHZ_TABLE": {
|
||||
"initial": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
100
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"CHANNEL_LABEL": {
|
||||
"description": "channel label",
|
||||
"CTRL_HIGH_Z_15": {
|
||||
"description": "ctrl highZ level",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "['current', 'voltage', 'impedance']"
|
||||
"initial": 1,
|
||||
"value": [
|
||||
"On",
|
||||
"Off"
|
||||
],
|
||||
"on_change": "set_ctrl_highZ"
|
||||
},
|
||||
"CYCLE_NUMBER": {
|
||||
"description": "CV cycle number",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
65536
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"SAMPLE_RATE": {
|
||||
"description": "data sampling rate",
|
||||
@@ -50,6 +77,12 @@
|
||||
},
|
||||
"on_change": "set_sample_rate"
|
||||
},
|
||||
"CHANNEL": {
|
||||
"derzteription": "record channels",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
},
|
||||
"AMP_GAIN": {
|
||||
"description": "amp gain",
|
||||
"record_meta": true,
|
||||
@@ -62,32 +95,95 @@
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Dev Mode"
|
||||
"Chronoamperometric",
|
||||
"V-T Graph",
|
||||
"R-T Graph",
|
||||
"EIS constant frequency",
|
||||
"Dev Mode",
|
||||
"Idle"
|
||||
]
|
||||
},
|
||||
"FREQ_START": {
|
||||
"description": "Start of Freq Scan",
|
||||
"GENERAL_HS_RTIA": {
|
||||
"description": "High speed rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 13422819,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"on_change": "set_general_hs_rtia"
|
||||
},
|
||||
"GENERAL_LP_RTIA": {
|
||||
"description": "Low power rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"auto"
|
||||
],
|
||||
"on_change": "set_general_lp_rtia"
|
||||
},
|
||||
"EIS_DC_BIAS": {
|
||||
"description": "DC voltage bias",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"FREQ_STOP": {
|
||||
"description": "End of Freq Scan",
|
||||
"EIS_AC_AMP": {
|
||||
"description": "AC Amplitude",
|
||||
"record_meta": true,
|
||||
"initial": 7,
|
||||
"initial": 26,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
2048
|
||||
]
|
||||
},
|
||||
"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",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
@@ -98,37 +194,56 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"AVERAGE_NUM": {
|
||||
"EIS_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
8,
|
||||
16
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"DC_BIAS": {
|
||||
"description": "DC voltage bias in mV",
|
||||
"CF_DC_BIAS": {
|
||||
"description": "DC voltage bias",
|
||||
"record_meta": true,
|
||||
"initial": 15000,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
35001
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"AC_AMP": {
|
||||
"description": "AC Amplitude in mV",
|
||||
"CF_AC_AMP": {
|
||||
"description": "AC Amplitude",
|
||||
"record_meta": true,
|
||||
"initial": 25,
|
||||
"initial": 26,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"SCALE": {
|
||||
"CF_FREQ": {
|
||||
"description": "frequency of cf",
|
||||
"record_meta": true,
|
||||
"initial": 13333333,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"CF_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
@@ -137,77 +252,29 @@
|
||||
1
|
||||
]
|
||||
},
|
||||
"PPD": {
|
||||
"description": "Point per decades",
|
||||
"CF_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"RTIA": {
|
||||
"description": "High speed tia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
]
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"Scan_Rate": {
|
||||
"description": "Voltage Scan Rate",
|
||||
"record_meta": true,
|
||||
"initial": 10000,
|
||||
"domain": [
|
||||
100001
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CTRL_HIGH_Z_15": {
|
||||
"description": "ctrl highZ level",
|
||||
"CF_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
"On",
|
||||
"Off"
|
||||
],
|
||||
"on_change": "set_ctrl_highZ"
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"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"
|
||||
],
|
||||
"on_change": "set_adc_gain_Vin"
|
||||
},
|
||||
"VOLT_INITIAL": {
|
||||
"CV_E_INITIAL": {
|
||||
"description": "Initial Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
@@ -218,8 +285,8 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_MAX": {
|
||||
"description": "Max Voltage of Scan",
|
||||
"CV_E1": {
|
||||
"description": "First voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
@@ -229,8 +296,8 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_MIN": {
|
||||
"description": "Min Voltage of Scan",
|
||||
"CV_E2": {
|
||||
"description": "Second voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
@@ -240,16 +307,54 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CYCLE_NUMBER": {
|
||||
"description": "CV cycle number",
|
||||
"CV_SCAN_RATE": {
|
||||
"description": "Voltage scan rate",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"initial": 10000,
|
||||
"domain": [
|
||||
100001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CA_VOLT": {
|
||||
"description": "Voltage of ca",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VT_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"
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
"description": "send msg to elite",
|
||||
@@ -266,43 +371,57 @@
|
||||
"domain": "int"
|
||||
}
|
||||
},
|
||||
|
||||
"instruction": {
|
||||
"start": [
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"7": "idle",
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"idle": [
|
||||
"_idle()"
|
||||
],
|
||||
"start_data": [
|
||||
"data_format_cali",
|
||||
"_notify(True)",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_Vin"
|
||||
"0": "set_general_hs_rtia",
|
||||
"1": "set_general_lp_rtia",
|
||||
"2": "set_general_lp_rtia",
|
||||
"3": "set_general_lp_rtia",
|
||||
"4": "set_general_lp_rtia",
|
||||
"5": "set_general_hs_rtia"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3"
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_ca",
|
||||
"3": "curve_vt",
|
||||
"4": "curve_rt",
|
||||
"5": "curve_cf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_para2",
|
||||
"1": "curve_cv3_para2"
|
||||
"1": "curve_cv3_para2",
|
||||
"5": "curve_cf_para2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_mode",
|
||||
"5": "curve_cf_mode"
|
||||
}
|
||||
},
|
||||
"_sync(True)",
|
||||
@@ -322,6 +441,18 @@
|
||||
"data_format_cali": [
|
||||
"_data_format_cali('EISZeroOne')"
|
||||
],
|
||||
"set_general_hs_rtia": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X70;1B>GENERAL_HS_RTIA"
|
||||
]
|
||||
},
|
||||
"set_general_lp_rtia": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X71;1B>GENERAL_LP_RTIA"
|
||||
]
|
||||
},
|
||||
"set_sample_rate": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
@@ -331,94 +462,172 @@
|
||||
"XE0;2B>va"
|
||||
]
|
||||
},
|
||||
"set_adc_gain_I": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"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": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE1;X03;B>CTRL_HIGH_Z_15"
|
||||
"1XFF;1X72;1B>CTRL_HIGH_Z_15"
|
||||
]
|
||||
},
|
||||
"curve_eis": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "FREQ_START",
|
||||
"fb": "FREQ_STOP",
|
||||
"dp": "DELAY",
|
||||
"dc": "DC_BIAS",
|
||||
"am": "AC_AMP",
|
||||
"an": "AVERAGE_NUM",
|
||||
"rt": "RTIA",
|
||||
"pp": "PPD",
|
||||
"sp": "SCALE"
|
||||
"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": [
|
||||
"1XD1;1X01;4B>fa;4B>fb;2B>dp"
|
||||
"1X12;1X01;4B>fa;4B>fb;2B>dp"
|
||||
]
|
||||
},
|
||||
"curve_eis_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "FREQ_START",
|
||||
"fb": "FREQ_STOP",
|
||||
"dp": "DELAY",
|
||||
"dc": "DC_BIAS",
|
||||
"am": "AC_AMP",
|
||||
"an": "AVERAGE_NUM",
|
||||
"rt": "RTIA",
|
||||
"pp": "PPD",
|
||||
"sp": "SCALE"
|
||||
"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": [
|
||||
"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_cf": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X01;4B>fa;4B>0;2B>dp"
|
||||
]
|
||||
},
|
||||
"curve_cf_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
|
||||
]
|
||||
},
|
||||
"curve_cf_mode": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1X13;1XFF"
|
||||
]
|
||||
},
|
||||
"curve_cv3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_INITIAL",
|
||||
"vb": "VOLT_MAX",
|
||||
"vc": "VOLT_MIN",
|
||||
"ve": "Scan_Rate",
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1XD2;1X01;2B>va;2B>vb;2B>vc;"
|
||||
"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",
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
|
||||
"1X09;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_ca": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CA_VOLT",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X0B;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_rt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "RT_VOLT_SET",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X04;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_vt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE",
|
||||
"va": "VT_MEASURE_VIN_RANGE"
|
||||
},
|
||||
"data": [
|
||||
"X05;",
|
||||
"4b>pa;4b>0;",
|
||||
"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_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
@@ -0,0 +1,655 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"HIGHZ_TABLE": {
|
||||
"initial": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
100
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"CTRL_HIGH_Z_15": {
|
||||
"description": "ctrl highZ level",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"value": [
|
||||
"On",
|
||||
"Off"
|
||||
],
|
||||
"on_change": "set_ctrl_highZ"
|
||||
},
|
||||
"CYCLE_NUMBER": {
|
||||
"description": "CV cycle number",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
65536
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"SAMPLE_RATE": {
|
||||
"description": "data sampling rate",
|
||||
"record_meta": true,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_sample_rate"
|
||||
},
|
||||
"CHANNEL": {
|
||||
"derzteription": "record channels",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
},
|
||||
"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",
|
||||
"EIS constant frequency",
|
||||
"Dev Mode",
|
||||
"Idle"
|
||||
]
|
||||
},
|
||||
"GENERAL_HS_RTIA": {
|
||||
"description": "High speed rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"on_change": "set_general_hs_rtia"
|
||||
},
|
||||
"GENERAL_LP_RTIA": {
|
||||
"description": "Low power rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"auto"
|
||||
],
|
||||
"on_change": "set_general_lp_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": 26,
|
||||
"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
|
||||
]
|
||||
},
|
||||
"CF_DC_BIAS": {
|
||||
"description": "DC voltage bias",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_AC_AMP": {
|
||||
"description": "AC Amplitude",
|
||||
"record_meta": true,
|
||||
"initial": 26,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"CF_FREQ": {
|
||||
"description": "frequency of cf",
|
||||
"record_meta": true,
|
||||
"initial": 13333333,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"CF_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"CF_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"CV_E_INITIAL": {
|
||||
"description": "Initial Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_E1": {
|
||||
"description": "First voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_E2": {
|
||||
"description": "Second voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_SCAN_RATE": {
|
||||
"description": "Voltage scan rate",
|
||||
"record_meta": true,
|
||||
"initial": 10000,
|
||||
"domain": [
|
||||
100001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CA_VOLT": {
|
||||
"description": "Voltage of ca",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VT_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"
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"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": {
|
||||
"7": "idle",
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"idle": [
|
||||
"_idle()"
|
||||
],
|
||||
"start_data": [
|
||||
"data_format_cali",
|
||||
"_notify(True)",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "set_general_hs_rtia",
|
||||
"1": "set_general_lp_rtia",
|
||||
"2": "set_general_lp_rtia",
|
||||
"3": "set_general_lp_rtia",
|
||||
"4": "set_general_lp_rtia",
|
||||
"5": "set_general_hs_rtia"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_ca",
|
||||
"3": "curve_vt",
|
||||
"4": "curve_rt",
|
||||
"5": "curve_cf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_para2",
|
||||
"1": "curve_cv3_para2",
|
||||
"5": "curve_cf_para2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_mode",
|
||||
"5": "curve_cf_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_general_lp_rtia": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X71;1B>GENERAL_LP_RTIA"
|
||||
]
|
||||
},
|
||||
"set_sample_rate": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"XE0;2B>va"
|
||||
]
|
||||
},
|
||||
"set_ctrl_highZ": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X72;1B>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_cf": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X01;4B>fa;4B>0;2B>dp"
|
||||
]
|
||||
},
|
||||
"curve_cf_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
|
||||
]
|
||||
},
|
||||
"curve_cf_mode": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1X13;1XFF"
|
||||
]
|
||||
},
|
||||
"curve_cv3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1X09;1X01;2B>va;2B>vb;2B>vc;"
|
||||
]
|
||||
},
|
||||
"curve_cv3_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1X09;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_ca": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CA_VOLT",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X0B;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_rt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "RT_VOLT_SET",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X04;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_vt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE",
|
||||
"va": "VT_MEASURE_VIN_RANGE"
|
||||
},
|
||||
"data": [
|
||||
"X05;",
|
||||
"4b>pa;4b>0;",
|
||||
"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,655 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"HIGHZ_TABLE": {
|
||||
"initial": [
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
100
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"CTRL_HIGH_Z_15": {
|
||||
"description": "ctrl highZ level",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"value": [
|
||||
"On",
|
||||
"Off"
|
||||
],
|
||||
"on_change": "set_ctrl_highZ"
|
||||
},
|
||||
"CYCLE_NUMBER": {
|
||||
"description": "CV cycle number",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
65536
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"SAMPLE_RATE": {
|
||||
"description": "data sampling rate",
|
||||
"record_meta": true,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_sample_rate"
|
||||
},
|
||||
"CHANNEL": {
|
||||
"derzteription": "record channels",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
},
|
||||
"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",
|
||||
"EIS constant frequency",
|
||||
"Dev Mode",
|
||||
"Idle"
|
||||
]
|
||||
},
|
||||
"GENERAL_HS_RTIA": {
|
||||
"description": "High speed rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"on_change": "set_general_hs_rtia"
|
||||
},
|
||||
"GENERAL_LP_RTIA": {
|
||||
"description": "Low power rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"auto"
|
||||
],
|
||||
"on_change": "set_general_lp_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": 26,
|
||||
"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
|
||||
]
|
||||
},
|
||||
"CF_DC_BIAS": {
|
||||
"description": "DC voltage bias",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_AC_AMP": {
|
||||
"description": "AC Amplitude",
|
||||
"record_meta": true,
|
||||
"initial": 26,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"CF_FREQ": {
|
||||
"description": "frequency of cf",
|
||||
"record_meta": true,
|
||||
"initial": 13333333,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"CF_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"CF_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CF_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"CV_E_INITIAL": {
|
||||
"description": "Initial Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_E1": {
|
||||
"description": "First voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_E2": {
|
||||
"description": "Second voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CV_SCAN_RATE": {
|
||||
"description": "Voltage scan rate",
|
||||
"record_meta": true,
|
||||
"initial": 10000,
|
||||
"domain": [
|
||||
100001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CA_VOLT": {
|
||||
"description": "Voltage of ca",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VT_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"
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"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": {
|
||||
"7": "idle",
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"idle": [
|
||||
"_idle()"
|
||||
],
|
||||
"start_data": [
|
||||
"data_format_cali",
|
||||
"_notify(True)",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "set_general_hs_rtia",
|
||||
"1": "set_general_lp_rtia",
|
||||
"2": "set_general_lp_rtia",
|
||||
"3": "set_general_lp_rtia",
|
||||
"4": "set_general_lp_rtia",
|
||||
"5": "set_general_hs_rtia"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_ca",
|
||||
"3": "curve_vt",
|
||||
"4": "curve_rt",
|
||||
"5": "curve_cf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_para2",
|
||||
"1": "curve_cv3_para2",
|
||||
"5": "curve_cf_para2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_mode",
|
||||
"5": "curve_cf_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_general_lp_rtia": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X71;1B>GENERAL_LP_RTIA"
|
||||
]
|
||||
},
|
||||
"set_sample_rate": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"XE0;2B>va"
|
||||
]
|
||||
},
|
||||
"set_ctrl_highZ": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1XFF;1X72;1B>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_cf": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X01;4B>fa;4B>0;2B>dp"
|
||||
]
|
||||
},
|
||||
"curve_cf_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "CF_FREQ",
|
||||
"dp": "CF_DELAY",
|
||||
"dc": "CF_DC_BIAS",
|
||||
"am": "CF_AC_AMP",
|
||||
"an": "CF_AVERAGE_NUM",
|
||||
"rt": "GENERAL_HS_RTIA",
|
||||
"pp": "CF_PPD",
|
||||
"sp": "CF_SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1X13;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
|
||||
]
|
||||
},
|
||||
"curve_cf_mode": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"1X13;1XFF"
|
||||
]
|
||||
},
|
||||
"curve_cv3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1X09;1X01;2B>va;2B>vb;2B>vc;"
|
||||
]
|
||||
},
|
||||
"curve_cv3_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CV_E_INITIAL",
|
||||
"vb": "CV_E1",
|
||||
"vc": "CV_E2",
|
||||
"ve": "CV_SCAN_RATE",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1X09;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_ca": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "CA_VOLT",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X0B;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_rt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "RT_VOLT_SET",
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X04;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>0;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_vt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "GENERAL_LP_RTIA",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE",
|
||||
"va": "VT_MEASURE_VIN_RANGE"
|
||||
},
|
||||
"data": [
|
||||
"X05;",
|
||||
"4b>pa;4b>0;",
|
||||
"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')"
|
||||
]
|
||||
}
|
||||
}
|
||||
+3
-11
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "EliteZM_pulsefly",
|
||||
"name": "Elite_MEGAFLY_0.1",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 2,
|
||||
"minor_product_number": 6,
|
||||
"major_version_number": 1,
|
||||
"minor_version_number": 7
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
"ADC_CHANNEL_NUMBER": [
|
||||
@@ -1426,14 +1426,6 @@
|
||||
"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": [
|
||||
"sti_mode",
|
||||
"gas1_mode",
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"name": "PEL_1.0",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite-PEL.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 7,
|
||||
"major_version_number": 0,
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
"TIME_MAX": 100000,
|
||||
"VOLT_MAX": 65536,
|
||||
"Const_Current_Range": 1500001,
|
||||
"BLE_WRITE_MAX": 255
|
||||
},
|
||||
"parameters": {
|
||||
"CHANNEL": {
|
||||
"description": "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
|
||||
},
|
||||
"PATTERN_SWITCH": {
|
||||
"description": "switch of pattern",
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
2
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"PULSE": {
|
||||
"description": "Pulse Mode Segment Duration 2",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
66536
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"PATTERN": {
|
||||
"description": "Pulse Mode Segment Duration 2",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
44
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
"start": [
|
||||
"pulse_e_load"
|
||||
],
|
||||
"pulse_e_load": [
|
||||
{
|
||||
"expression": "PATTERN_SWITCH",
|
||||
"when": {
|
||||
"0": "pattern",
|
||||
"1": "manual"
|
||||
}
|
||||
}
|
||||
],
|
||||
"manual": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "PULSE[0]",
|
||||
"pb": "PULSE[1]",
|
||||
"pc": "PULSE[2]"
|
||||
},
|
||||
"data": [
|
||||
"XFF;",
|
||||
"X62;",
|
||||
"4b1;4b>pa;4b>pb;4b>pc;"
|
||||
]
|
||||
},
|
||||
"pattern": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "PATTERN"
|
||||
},
|
||||
"data": [
|
||||
"XFF;X62;",
|
||||
"4b>0;12b>pa;"
|
||||
]
|
||||
},
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"name": "PEL_2.0",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Elite-PEL.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 7,
|
||||
"major_version_number": 0,
|
||||
"minor_version_number": 1
|
||||
},
|
||||
"constant": {
|
||||
"TIME_MAX": 100000,
|
||||
"VOLT_MAX": 65536,
|
||||
"Const_Current_Range": 1500001,
|
||||
"BLE_WRITE_MAX": 255
|
||||
},
|
||||
"parameters": {
|
||||
"CHANNEL": {
|
||||
"description": "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,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"Select Resistor Mode",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"PATTERN_SWITCH": {
|
||||
"description": "switch of pattern",
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
2
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"PULSE": {
|
||||
"description": "Pulse Mode Segment Duration 2",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
66536
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"PATTERN": {
|
||||
"description": "Pulse Mode Segment Duration 2",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
44
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
"start": [
|
||||
"pulse_e_load"
|
||||
],
|
||||
"pulse_e_load": [
|
||||
{
|
||||
"expression": "PATTERN_SWITCH",
|
||||
"when": {
|
||||
"0": "pattern",
|
||||
"1": "manual"
|
||||
}
|
||||
}
|
||||
],
|
||||
"manual": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "PULSE[0]",
|
||||
"pb": "PULSE[1]",
|
||||
"pc": "PULSE[2]"
|
||||
},
|
||||
"data": [
|
||||
"XFF;",
|
||||
"X62;",
|
||||
"4b1;4b>pa;4b>pb;4b>pc;"
|
||||
]
|
||||
},
|
||||
"pattern": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "PATTERN"
|
||||
},
|
||||
"data": [
|
||||
"XFF;X62;",
|
||||
"4b>0;12b>pa;"
|
||||
]
|
||||
},
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"ble_write": {
|
||||
"type": "ALL",
|
||||
"data": [
|
||||
"255X>BLE_WRITE;"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
{
|
||||
"name": "Elite_TRI",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Trigger.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 5,
|
||||
"major_version_number": 1,
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
|
||||
},
|
||||
"parameters": {
|
||||
"ACC_a_out0": {
|
||||
"description": "Switch of analog current channel 1",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"on_change": "set_para_AOUT0"
|
||||
},
|
||||
"ACC_a_out0_current": {
|
||||
"description": "current value of analog current channel 1",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_para_AOUT0"
|
||||
},
|
||||
"ACC_a_out1": {
|
||||
"description": "Switch of analog current channel 2",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"on_change": "set_para_AOUT1"
|
||||
},
|
||||
"ACC_a_out1_current": {
|
||||
"description": "current value of analog current channel 2",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_para_AOUT1"
|
||||
},
|
||||
"ACC_a_out2": {
|
||||
"description": "Switch of analog current channel 3",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"on_change": "set_para_AOUT2"
|
||||
},
|
||||
"ACC_a_out2_current": {
|
||||
"description": "current value of analog current channel 3",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_para_AOUT2"
|
||||
},
|
||||
"ACC_a_out3": {
|
||||
"description": "Switch of current channel 4",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"on_change": "set_para_AOUT3"
|
||||
},
|
||||
"ACC_a_out3_current": {
|
||||
"description": "current value of analog current channel 4",
|
||||
"record_meta": true,
|
||||
"initial":0,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_para_AOUT3"
|
||||
},
|
||||
"TRIG0_en": {
|
||||
"description": "Switch of current channel 4",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"TRIG1_en": {
|
||||
"description": "Switch of current channel 4",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"TRIG0_edge_type": {
|
||||
"description": "Switch of current channel 4",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"RISING",
|
||||
"FALLING",
|
||||
"BOTH"
|
||||
]
|
||||
},
|
||||
"TRIG1_edge_type": {
|
||||
"description": "Switch of current channel 4",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"RISING",
|
||||
"FALLING",
|
||||
"BOTH"
|
||||
]
|
||||
},
|
||||
"MODE": {
|
||||
"description": "working mode",
|
||||
"record_meta": true,
|
||||
"value": [
|
||||
"Analog Current Control (ACC)"
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"CHANNEL": {
|
||||
"description": "delete it",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
},
|
||||
"CHANNEL_LABEL": {
|
||||
"description": "delete it",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "['current', 'voltage', 'impedance']"
|
||||
},
|
||||
"SAMPLE_RATE": {
|
||||
"description": "delete it",
|
||||
"record_meta": true,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_sample_rate"
|
||||
},
|
||||
"AMP_GAIN": {
|
||||
"description": "delete it",
|
||||
"record_meta": true,
|
||||
"domain": "constant",
|
||||
"value": 1
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
"start": [
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"start_data": [
|
||||
"data_format",
|
||||
"_notify(True)",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "set_aout_chan_en"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "set_TRIG_EN"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_acc"
|
||||
}
|
||||
},
|
||||
"_sync(True)",
|
||||
"VIS_STI"
|
||||
],
|
||||
"data_format": [
|
||||
"_data_format('I4V4Z4T4')",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "_disable_cache(True)",
|
||||
"1": "_disable_cache(True)",
|
||||
"*": "_disable_cache(False)"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dev_version": [
|
||||
"CIS_VERSION",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"dev_battery": [
|
||||
"CIS_VOLT",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"curve_acc": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "ACC_a_out0_current",
|
||||
"vb": "ACC_a_out1_current",
|
||||
"vc": "ACC_a_out2_current",
|
||||
"vd": "ACC_a_out3_current"
|
||||
},
|
||||
"data": [
|
||||
"X0E;",
|
||||
"2B>va;2B>vb;2B>vc;2B>vd"
|
||||
]
|
||||
},
|
||||
"set_aout_chan_en": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "ACC_a_out0",
|
||||
"vb": "ACC_a_out1",
|
||||
"vc": "ACC_a_out2",
|
||||
"vd": "ACC_a_out3"
|
||||
},
|
||||
"data": [
|
||||
"X81;X02;",
|
||||
"4b>va;4b>vb;4b>vc;4b>vd"
|
||||
]
|
||||
},
|
||||
"set_TRIG_EN": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "TRIG0_en",
|
||||
"vb": "TRIG1_en",
|
||||
"vc": "TRIG0_edge_type",
|
||||
"vd": "TRIG1_edge_type"
|
||||
},
|
||||
"data": [
|
||||
"X41;",
|
||||
"4b>va;4b>vb;4b>vc;4b>vd"
|
||||
]
|
||||
},
|
||||
"set_para_AOUT0": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE2;X02;X00;2B>ACC_a_out0_current;1B>ACC_a_out0"
|
||||
]
|
||||
},
|
||||
"set_para_AOUT1": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE2;X02;X01;2B>ACC_a_out1_current;1B>ACC_a_out1"
|
||||
]
|
||||
},
|
||||
"set_para_AOUT2": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE2;X02;X02;2B>ACC_a_out2_current;1B>ACC_a_out2"
|
||||
]
|
||||
},
|
||||
"set_para_AOUT3": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE2;X02;X03;2B>ACC_a_out3_current;1B>ACC_a_out3"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# install python module numpy
|
||||
sudo apt-get install libatlas-base-dev
|
||||
sudo apt-get install python3-numpy
|
||||
|
||||
# install python module SQLAlchemy
|
||||
pip3 install SQLAlchemy
|
||||
|
||||
# create folder to save project logger
|
||||
mkdir -p /home/pi/logger/project
|
||||
|
||||
# add column cycle in projects
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS cycle JSONB;\"" postgres
|
||||
|
||||
# add column project in recording_data_metas
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE recording_data_metas ADD COLUMN IF NOT EXISTS project Int4;\"" postgres
|
||||
|
||||
# remove default controller info
|
||||
sudo su -c "psql -d postgres -c \"DELETE FROM controllers WHERE name='WTP_NONE';\"" postgres
|
||||
|
||||
# change table name from meta_project_info to project_metas
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE IF EXISTS meta_project_info RENAME TO project_metas;\"" postgres
|
||||
|
||||
# change table name from project_report to project_reports
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE IF EXISTS project_report RENAME TO project_reports;\"" postgres
|
||||
|
||||
# change table project_meta column cycle to type jsonb
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE project_metas ALTER COLUMN cycle type jsonb USING (cycle::jsonb);\"" postgres
|
||||
|
||||
# drop column calibration default
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ALTER COLUMN calibration DROP DEFAULT;\"" postgres
|
||||
|
||||
# drop column calibration default
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ALTER COLUMN calibration TYPE bytea USING calibration::bytea;\"" postgres
|
||||
|
||||
# add column project in recording_data_metas
|
||||
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ADD COLUMN IF NOT EXISTS calibration_version Int4 DEFAULT -1;\"" postgres
|
||||
Reference in New Issue
Block a user