Compare commits
160 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e152e56031 | |||
| 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 |
@@ -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:
|
||||
@@ -432,12 +433,12 @@ class CC2650Device(Device):
|
||||
if length == 1 and instruction[0] < 0:
|
||||
return struct.pack('2B1b',
|
||||
(ins_type & 0xF0) | (self.device_id & 0x0F),
|
||||
(ins_oper & 0xF0) | (length & 0x0F),
|
||||
(ins_oper & 0xFF),
|
||||
*instruction)
|
||||
|
||||
return struct.pack('%dB' % (length + 2),
|
||||
(ins_type & 0xF0) | (self.device_id & 0x0F),
|
||||
(ins_oper & 0xF0) | (length & 0x0F),
|
||||
(ins_oper & 0xFF),
|
||||
*instruction)
|
||||
|
||||
def _decode_data(self, ins_oper: int, data: bytes) -> bytes:
|
||||
@@ -469,6 +470,7 @@ class CC2650Device(Device):
|
||||
# receive
|
||||
data = self._master.read_characteristic(self.device_id, CC2650MasterDevice.RETURN_HANDLE)
|
||||
data = self._decode_data(DeviceInstruction.CIS_VERSION, data)
|
||||
print('data:',list(data))
|
||||
|
||||
except SendInstructionTimeoutError:
|
||||
self._master.log_warn('device', self.device_id, 'update_device_version no response')
|
||||
@@ -477,18 +479,14 @@ 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]
|
||||
|
||||
self._device_version = str(year) + '/' + str(month) + '/' + str(day) + " " + str(hour) + ":" + str(
|
||||
minute) + " | " + str(mac1) + ":" + str(mac2)
|
||||
minute)
|
||||
|
||||
@property
|
||||
def battery(self) -> int:
|
||||
@@ -537,7 +535,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 +547,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 +602,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 +677,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 +1958,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 +1984,144 @@ 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()
|
||||
|
||||
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')
|
||||
|
||||
else:
|
||||
try:
|
||||
scan_response = self._cc2650.recv_uart(0.01)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_verbose('[CC2650]', 'scan_callback response timeout, no device')
|
||||
return False
|
||||
|
||||
if scan_response is None:
|
||||
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 +2131,163 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
addr_type = response.addr_type
|
||||
address_s = cc2650.address_str(address)
|
||||
|
||||
self.log_info(DEVICE_CONNECTING, address_s)
|
||||
connect_response = None
|
||||
ins = bytearray()
|
||||
|
||||
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
|
||||
|
||||
# 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)
|
||||
print('!!connect_response:', list(connect_response))
|
||||
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:
|
||||
return False
|
||||
|
||||
pack_len = connect_response[0]
|
||||
connect_ack = connect_response[1:pack_len+1]
|
||||
|
||||
if connect_ack == [3]:
|
||||
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
|
||||
self.log_verbose('[CC2650]', 'connect success', '0x'+connect_response_hex)
|
||||
# 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
|
||||
|
||||
self.log_verbose('[CC2650]', 'connect fail')
|
||||
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 _ 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
|
||||
|
||||
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)
|
||||
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:
|
||||
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 +2388,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 +2445,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,9 @@ 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 isinstance(device, DebugDevice):
|
||||
if func == InternalInstruction.PREDEFINED_NOTIFY:
|
||||
@@ -848,6 +854,11 @@ 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 _device_data_format_cali(self, device: Device, expr: str, cali: bytes = None):
|
||||
if cali is None:
|
||||
cali = device.calibration_info(expr)
|
||||
|
||||
+369
-182
@@ -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,7 @@ 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')
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -868,6 +869,8 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
self._mode = 0
|
||||
self._cycle_start_time = []
|
||||
|
||||
self._show_data = False
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.NAME
|
||||
@@ -881,21 +884,55 @@ 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
|
||||
ram_num = data[47]
|
||||
@@ -919,25 +956,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 +989,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 +1383,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,86 +1398,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)
|
||||
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)
|
||||
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)
|
||||
#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)
|
||||
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)
|
||||
#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('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:
|
||||
@@ -1440,10 +1634,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
|
||||
@@ -1461,9 +1655,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
|
||||
|
||||
@@ -1471,7 +1670,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)
|
||||
@@ -1480,101 +1679,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())
|
||||
@@ -1583,17 +1764,23 @@ 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(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(3, cycle_number)
|
||||
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(0, ch1) #Iin [nA]
|
||||
|
||||
@@ -651,8 +651,6 @@ class DeviceInstruction:
|
||||
VIS_DEVICE_DONE = 0x20
|
||||
"""identify device done"""
|
||||
|
||||
VIS_CC_ZERO = 0x40
|
||||
|
||||
VIS_STI = 0xC0
|
||||
"""stimulation on virtual instruction"""
|
||||
|
||||
@@ -726,7 +724,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'
|
||||
|
||||
@@ -741,7 +738,7 @@ 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.CALL:
|
||||
@@ -750,8 +747,6 @@ class DeviceCommonInstruction:
|
||||
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:
|
||||
|
||||
@@ -283,6 +283,7 @@ class InternalInstruction(SingleInstruction):
|
||||
PREDEFINED_SET = '_set'
|
||||
PREDEFINED_CDR = '_cdr'
|
||||
PREDEFINED_DISABLE_CACHE = '_disable_cache'
|
||||
PREDEFINED_IDLE = '_idle'
|
||||
|
||||
PREDEFINED = (
|
||||
PREDEFINED_SLEEP,
|
||||
@@ -294,6 +295,7 @@ class InternalInstruction(SingleInstruction):
|
||||
PREDEFINED_SET,
|
||||
PREDEFINED_CDR,
|
||||
PREDEFINED_DISABLE_CACHE,
|
||||
PREDEFINED_IDLE,
|
||||
)
|
||||
|
||||
__slots__ = ('_expr', '_para')
|
||||
@@ -370,6 +372,7 @@ class InternalInstruction(SingleInstruction):
|
||||
|
||||
else:
|
||||
data = [v for v in data]
|
||||
print('cdr data:', data)
|
||||
|
||||
parser.parse_instruction(context, data)
|
||||
|
||||
@@ -774,6 +777,12 @@ class InstructionDataContent(InstructionContent):
|
||||
|
||||
def parse_instruction(self, context: Scope, buffer: List[int], offset: int = 0, shift: int = 0) -> Tuple[int, int]:
|
||||
|
||||
print('self._width', self._width)
|
||||
print('self._width.size', self._width.size)
|
||||
|
||||
for _ in range (self._width.size - len(buffer)):
|
||||
buffer.append(0)
|
||||
|
||||
if self._width.is_array:
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -787,21 +796,20 @@ class InstructionDataContent(InstructionContent):
|
||||
|
||||
value = 0
|
||||
|
||||
if self._width.size == 1:
|
||||
value = buffer[offset]
|
||||
for i in range(self._width.size):
|
||||
if self._width.little_endian:
|
||||
value |= (buffer[offset] << (1 * i))
|
||||
else:
|
||||
value = (value << 8) | buffer[offset]
|
||||
offset += 1
|
||||
|
||||
else:
|
||||
for i in range(self._width.size):
|
||||
if self._width.little_endian:
|
||||
value |= (buffer[offset] << (1 * i))
|
||||
else:
|
||||
value = (value << 8) | buffer[offset]
|
||||
offset += 1
|
||||
|
||||
if len(self._value) > 0:
|
||||
context[self._value] = value
|
||||
|
||||
print('value',value)
|
||||
print('hex(value)',hex(value))
|
||||
|
||||
|
||||
return offset, 0
|
||||
|
||||
else:
|
||||
@@ -819,7 +827,6 @@ class InstructionDataContent(InstructionContent):
|
||||
if self._width.bytes_unit:
|
||||
if shift != 0:
|
||||
offset += 1
|
||||
|
||||
return offset + self._width.size, 0
|
||||
|
||||
else:
|
||||
|
||||
@@ -968,7 +968,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):
|
||||
"""
|
||||
@@ -986,6 +986,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
|
||||
@@ -1032,7 +1034,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:
|
||||
@@ -1082,6 +1084,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]:
|
||||
@@ -1105,6 +1115,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)
|
||||
@@ -1128,6 +1140,11 @@ class CompletedDevice(Device):
|
||||
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
|
||||
@@ -1296,6 +1313,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),
|
||||
}
|
||||
|
||||
@@ -1385,20 +1403,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -98,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
|
||||
@@ -216,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 = []
|
||||
|
||||
@@ -300,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)
|
||||
@@ -415,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)
|
||||
|
||||
|
||||
@@ -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]:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -317,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
|
||||
@@ -345,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']
|
||||
@@ -354,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)
|
||||
|
||||
@@ -380,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
|
||||
@@ -406,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)
|
||||
|
||||
@@ -646,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
|
||||
@@ -654,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()
|
||||
@@ -662,15 +674,18 @@ 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)
|
||||
# self._no_data_total_duration = 0
|
||||
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
|
||||
@@ -699,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()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from time import sleep
|
||||
from typing import Iterable
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
import biopro.impl.vcgencmd as vcg
|
||||
from biopro.data import DataServerOptions, DataAPI
|
||||
@@ -31,8 +32,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 +109,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 +121,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 +133,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 +827,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 +863,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_1.1'):
|
||||
# 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 +900,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 +1037,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 +1055,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 +1088,10 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE:
|
||||
return True
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_IDLE:
|
||||
device.status = 1
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
@@ -1059,6 +1106,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 +1118,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 +1158,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 +1391,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
|
||||
@@ -607,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:
|
||||
|
||||
+6
-16
@@ -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,
|
||||
@@ -780,7 +780,7 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_VSCAN": {
|
||||
"CA_VOLT": {
|
||||
"description": "Voltage of VScan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
@@ -1203,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;",
|
||||
@@ -1301,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",
|
||||
@@ -1633,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
+367
-171
@@ -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,14 +95,68 @@
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Dev Mode"
|
||||
"Chronoamperometric",
|
||||
"V-T Graph",
|
||||
"R-T Graph",
|
||||
"EIS constant frequency",
|
||||
"Dev Mode",
|
||||
"Idle"
|
||||
]
|
||||
},
|
||||
"FREQ": {
|
||||
"description": "DPV current recording period start",
|
||||
"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": [
|
||||
13422819,
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
@@ -79,29 +166,24 @@
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"FREQ_START": {
|
||||
"description": "Start of Freq Scan",
|
||||
"EIS_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 13422819,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
11
|
||||
]
|
||||
},
|
||||
"FREQ_STOP": {
|
||||
"description": "End of Freq Scan",
|
||||
"EIS_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 7,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"DELAY": {
|
||||
"EIS_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
@@ -112,19 +194,19 @@
|
||||
"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": 25000,
|
||||
"domain": [
|
||||
@@ -134,15 +216,34 @@
|
||||
"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,
|
||||
@@ -151,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,
|
||||
@@ -232,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": [
|
||||
@@ -243,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": [
|
||||
@@ -254,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",
|
||||
@@ -285,37 +376,52 @@
|
||||
{
|
||||
"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)",
|
||||
@@ -335,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": {
|
||||
@@ -344,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[0]",
|
||||
"fb": "FREQ[1]",
|
||||
"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[0]",
|
||||
"fb": "FREQ[1]",
|
||||
"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",
|
||||
+16
-4
@@ -1,17 +1,28 @@
|
||||
{
|
||||
"name": "Elite_TRI",
|
||||
"name": "Elite_TRIG_0.1",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Trigger.*",
|
||||
"local_name_pattern": "Elite.*",
|
||||
"major_product_number": 0,
|
||||
"minor_product_number": 5,
|
||||
"major_version_number": 1,
|
||||
"minor_version_number": 0
|
||||
},
|
||||
"constant": {
|
||||
|
||||
"TIME_MAX": 100000
|
||||
},
|
||||
"parameters": {
|
||||
"TIME_DURATION": {
|
||||
"description": "timer",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
"TIME_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"ACC_a_out0": {
|
||||
"description": "Switch of analog current channel 1",
|
||||
"record_meta": true,
|
||||
@@ -142,7 +153,8 @@
|
||||
"description": "working mode",
|
||||
"record_meta": true,
|
||||
"value": [
|
||||
"Analog Current Control (ACC)"
|
||||
"Analog Current Control (ACC)",
|
||||
"Idle"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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,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