Compare commits
150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 695f37c2dd | |||
| 690f859e86 | |||
| 959d86c0fe | |||
| 24c07a7fa5 | |||
| e43857a5bc | |||
| c084f29f06 | |||
| 130d260add | |||
| 575d5d8af1 | |||
| fbf6297047 | |||
| c540013d19 | |||
| 7f0b00a323 | |||
| 4828c85668 | |||
| 4ce9fe5b8d | |||
| d74f09254e | |||
| 79ecff69cc | |||
| df45126ead | |||
| 9fade3469a | |||
| a77331176c | |||
| 8f98337267 | |||
| 205d39cb11 | |||
| a5ea3243fa | |||
| 2edf28c7ba | |||
| 5531dcc0f0 | |||
| b20d46daa8 | |||
| 789d9b3a81 | |||
| 0d0427ed14 | |||
| d434509c5b | |||
| 787d76d48c | |||
| 50f2432088 | |||
| 1cff19ac58 | |||
| baef447c0e | |||
| ee9c13d4c5 | |||
| 9076f2f10b | |||
| 9b2e2964b0 | |||
| 2622109c89 | |||
| a3fe6b87af | |||
| 64419ca1c5 | |||
| 7d77c44741 | |||
| 29b4dd5cc7 | |||
| f151ae6fce | |||
| e535e3d2b1 | |||
| 06c36aa737 | |||
| 402022c451 | |||
| c0bb567bf7 | |||
| 4daff72d39 | |||
| f99719832a | |||
| 58e09bfcda | |||
| 55780514b9 | |||
| 936514871f | |||
| f25d9221c6 | |||
| 2ee9fa6b19 | |||
| fcc39dbfed | |||
| e2f7bba961 | |||
| 1174d54bc0 | |||
| bff75dc49e | |||
| 35912f614e | |||
| cfc4e39c8a | |||
| 8c4916d1e8 | |||
| e3c252f204 | |||
| c2164da48b | |||
| ab2d746afb | |||
| 8a870a860a | |||
| f4c5cf0135 | |||
| 1f01fd3b9b | |||
| d1fe388c27 | |||
| 91d5e73c5e | |||
| d1b6c2892f | |||
| 4243a13536 | |||
| 97188abff8 | |||
| 9d8178d11a | |||
| bbde653a8e | |||
| 6c0cef7925 | |||
| 3bbf0c912a | |||
| 4333958ebe | |||
| 3239a691e3 | |||
| 30183788d8 | |||
| 13df921b1c | |||
| d182a04ed3 | |||
| 35a09ff9a0 | |||
| e134b9780c | |||
| df39f241b3 | |||
| 0b72ac0c9d | |||
| 0afbe66229 | |||
| 9846cfd708 | |||
| b4ad2a7fba | |||
| 675fdc2226 | |||
| a847b1222d | |||
| bd0c36923a | |||
| 612785f51a | |||
| 7dbf09e9a5 | |||
| ee64d43de1 | |||
| 60b91f0c1e | |||
| 8ac01bdf54 | |||
| 0f90b16b6e | |||
| cd98a14e84 | |||
| 2e97ad23eb | |||
| e0dd5a6972 | |||
| 76e0a150d1 | |||
| ecd4b9325d | |||
| 978b1254f0 | |||
| 26e02f2d40 | |||
| ead98fe8da | |||
| 257958768f | |||
| dc4e1bd233 | |||
| 42025d2243 | |||
| b341dbf073 | |||
| 20f6f126b0 | |||
| bf4a00db1a | |||
| 0b7a650b95 | |||
| 062613c681 | |||
| bffaff310b | |||
| 06bf262d59 | |||
| b2f9d98336 | |||
| a6b523404b | |||
| 6c232b3b07 | |||
| cfc2bf1d83 | |||
| 2b60e68197 | |||
| efb5e9aeb6 | |||
| b4d88a0e67 | |||
| 6029ff6fe1 | |||
| 6efc5e1097 | |||
| a23394d3d1 | |||
| c96f76f438 | |||
| f0f1c9fc49 | |||
| 512c80af40 | |||
| 499964b287 | |||
| 16f12d40bf | |||
| 63c1ba8efb | |||
| 4a28348db4 | |||
| 64dfe87d05 | |||
| f7a5a867a4 | |||
| 1accaa9b9f | |||
| b810e35fb2 | |||
| 82c9d2b0e3 | |||
| e5a3f33b9f | |||
| 1dd4ae2ce4 | |||
| 515cc9f7a2 | |||
| 9b92249fdb | |||
| adcc13b4de | |||
| 0cd0fd7027 | |||
| 5228290eac | |||
| fa8c219f76 | |||
| ced466f3aa | |||
| f36906c034 | |||
| 0b5c62e525 | |||
| abe86238ca | |||
| f9ab0bc59b | |||
| 5dbe231c73 | |||
| c721950bf7 | |||
| 70c0271771 |
@@ -1,7 +1,10 @@
|
||||
.DS_Store
|
||||
*.cpython-37.opt-2.pyc
|
||||
*.cpython-39-arm-linux-gnueabihf.so
|
||||
*.
|
||||
*.pyc
|
||||
*/__pycache__
|
||||
/.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
|
||||
```
|
||||
@@ -358,3 +361,22 @@ $sudo vim ./sites-available/000-default.conf
|
||||
|
||||
##### raspberry website document:
|
||||
> https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
|
||||
|
||||
# ChangeLog
|
||||
[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
|
||||
|
||||
|
||||
|
||||
@@ -1578,10 +1578,22 @@ class ControlAPI(metaclass=Router):
|
||||
raise NotImplementedError()
|
||||
|
||||
def run_project(self, project) -> bool:
|
||||
print('create_project', project)
|
||||
self._project_manager.create(project)
|
||||
return False
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_running_project(self) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def stop_project(self, project) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_project(self, project, content) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_project_cycle(self, project, index, content) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def show_device_data(self, device) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
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,21 @@
|
||||
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 MetaProjectInfo(Base):
|
||||
__tablename__ = "meta_project_info"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
project = Column(String(36))
|
||||
cycle = Column(String)
|
||||
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())
|
||||
|
||||
# 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_report"
|
||||
|
||||
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})"
|
||||
@@ -662,7 +662,7 @@ class CC2650Device(Device):
|
||||
elif device_type == 'EISZeroOne':
|
||||
i = 0
|
||||
request_times = 0
|
||||
while i < 7:
|
||||
while i < 13:
|
||||
try:
|
||||
# send
|
||||
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
|
||||
|
||||
@@ -253,6 +253,7 @@ class DeviceInternalCommandHandler:
|
||||
return True
|
||||
|
||||
|
||||
# why inherit MasterDevice ?
|
||||
class DeviceManager(MasterDevice, Synchronized):
|
||||
"""device manager. It manager the device libraries, found device, connected device
|
||||
and the control of the master device.
|
||||
@@ -267,7 +268,6 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
options: DeviceManagerOptions,
|
||||
handler: Optional[DeviceInternalCommandHandler] = None):
|
||||
"""
|
||||
|
||||
:param options: manager options.
|
||||
:param handler: device internal command handler
|
||||
"""
|
||||
@@ -277,6 +277,7 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
if handler is None:
|
||||
handler = DeviceInternalCommandHandler()
|
||||
|
||||
# control server api
|
||||
self._handler: DeviceInternalCommandHandler = handler
|
||||
self._options: DeviceManagerOptions = options
|
||||
|
||||
@@ -286,7 +287,9 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
# hardware
|
||||
self._interface = options.interface
|
||||
self._master: Optional[MasterDevice] = None
|
||||
# memory board
|
||||
self._centralMaster: Optional[MasterDevice] = None
|
||||
# connected device
|
||||
self._device: List[CompletedDevice] = []
|
||||
|
||||
# demo device
|
||||
@@ -336,6 +339,10 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
def library_path(self) -> List[Path]:
|
||||
return self._repository.library_path
|
||||
|
||||
def get_device_status(self, mac_address) -> Optional[DeviceLibrary]:
|
||||
device = self.get_device(mac_address)
|
||||
return device.status
|
||||
|
||||
@logging_info
|
||||
def reload_library(self):
|
||||
"""reload device library"""
|
||||
@@ -562,26 +569,28 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
|
||||
@logging_verbose
|
||||
def get_device(self, device: Union[int, DeviceInfo]) -> Optional[CompletedDevice]:
|
||||
print('get_device', device)
|
||||
"""get connected device
|
||||
|
||||
: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
|
||||
|
||||
@@ -823,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:
|
||||
@@ -842,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)
|
||||
@@ -1024,15 +1041,9 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
raise RuntimeError(DEVICE_NOT_FOUND, device)
|
||||
|
||||
if DeviceCommonInstruction(instruction) is not None:
|
||||
# print('deviceCommonInstr')
|
||||
# print(instruction)
|
||||
device.call_instruction(instruction)
|
||||
|
||||
elif instruction in device.library.instruction_table:
|
||||
# print('instruction')
|
||||
# print(instruction)
|
||||
device.call_instruction(instruction)
|
||||
|
||||
else:
|
||||
raise RuntimeError(INSTRUCTION_UNKNOWN, instruction)
|
||||
|
||||
|
||||
+177
-110
@@ -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,16 +884,21 @@ 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
|
||||
voltage = struct.unpack('<i', data[12:16])[0] # unit: uV
|
||||
impedance = struct.unpack('<i', data[16:20])[0] # unit: mOm
|
||||
|
||||
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]
|
||||
notify_one = struct.unpack('<i', data[28:32])[0]
|
||||
notify_two = struct.unpack('<i', data[32:36])[0]
|
||||
notify_three = struct.unpack('<i', data[36:40])[0]
|
||||
# self._show_data = True
|
||||
|
||||
mem_wrong_information = struct.unpack('<i', data[43:47])[0] # mem_wrong_information = green retry, green wrong, red retry, red wrong
|
||||
ram_num = data[47]
|
||||
@@ -914,9 +922,11 @@ 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),
|
||||
'|', current, '|', voltage, '|', impedance, '|', cycle_number,
|
||||
'|', notify_one, '|', notify_two, '|', notify_three,
|
||||
'|', finishMode, '@', str(self.device))
|
||||
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:4}'.format(delta),
|
||||
@@ -945,18 +955,21 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
ret.append_data(1, voltage)
|
||||
ret.append_data(2, impedance)
|
||||
ret.append_data(3, cycle_number)
|
||||
ret.append_data(4, battery)
|
||||
ret.append_data(5, elite_notify_times)
|
||||
ret.append_data(6, mem_cnt)
|
||||
ret.append_data(4, notify_one)
|
||||
ret.append_data(5, notify_two)
|
||||
ret.append_data(6, notify_three)
|
||||
# ret.append_data(4, battery)
|
||||
# ret.append_data(5, elite_notify_times)
|
||||
# ret.append_data(6, mem_cnt)
|
||||
|
||||
# memoryboard information
|
||||
ret.append_data(7, ram_num)
|
||||
ret.append_data(8, broken_flag)
|
||||
try:
|
||||
ret.append_data(9, mem_wrong_information)
|
||||
# print('append_data success, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
|
||||
except:
|
||||
print('append_data fail, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
|
||||
# # memoryboard information
|
||||
# ret.append_data(7, ram_num)
|
||||
# ret.append_data(8, broken_flag)
|
||||
# try:
|
||||
# ret.append_data(9, mem_wrong_information)
|
||||
# # print('append_data success, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
|
||||
# except:
|
||||
# print('append_data fail, mem_wrong_information:', mem_wrong_information, hex(mem_wrong_information))
|
||||
|
||||
|
||||
|
||||
@@ -1333,8 +1346,8 @@ 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')
|
||||
'cali_coeff', '_ac_amp', '_mode',
|
||||
'_last_phase', '_first_phase_flag', '_show_data')
|
||||
|
||||
def __init__(self, cali_coeff: bytes = None):
|
||||
super().__init__()
|
||||
@@ -1349,15 +1362,14 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
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_coeff: Optional[List[Tuple[int, int]]] = None
|
||||
|
||||
self._show_data = False
|
||||
|
||||
if cali_coeff is not None:
|
||||
self._cali_coeff = cali_coeff
|
||||
self.cali_coeff = self._decode_cali_coeff(cali_coeff)
|
||||
@@ -1366,12 +1378,27 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]:
|
||||
if cali_coeff != b'':
|
||||
cali_table = []
|
||||
phase_para_a = []
|
||||
phase_para_b = []
|
||||
hsrtia_a = []
|
||||
hsrtia_b = []
|
||||
hsrtia_c = []
|
||||
hsrtia_d = []
|
||||
phase_coeff = []
|
||||
phase_offset = []
|
||||
|
||||
# phase_coeff = [[0]*4 for i in range(4)]
|
||||
# phase_offset = [[0]*4 for i in range(4)]
|
||||
|
||||
phase_coeff = numpy.zeros([4, 4], dtype = int)
|
||||
phase_offset = numpy.zeros([4, 4], dtype = int)
|
||||
|
||||
########################################
|
||||
# phase_coeff
|
||||
# [[gain0, g1, g2, g3] ----->最高頻
|
||||
# [gain0, g1, g2, g3] ----->中頻
|
||||
# [gain0, g1, g2, g3] ----->低頻
|
||||
# [gain0, g1, g2, g3] ----->最低頻
|
||||
# ]
|
||||
#######################################
|
||||
|
||||
# print('cali_coeff', cali_coeff)
|
||||
cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4
|
||||
@@ -1382,57 +1409,95 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
|
||||
|
||||
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])
|
||||
|
||||
g = 0
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 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])
|
||||
|
||||
g = 0
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
#Lv[0] 160k
|
||||
index = 60
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
|
||||
|
||||
#Lv[1] 20k
|
||||
index = 80
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
|
||||
|
||||
#Lv[2] 5k
|
||||
index = 100
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
|
||||
|
||||
#Lv[3] 200R
|
||||
index = 120
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0])
|
||||
|
||||
# hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0])
|
||||
# hsrtia_b.append(struct.unpack('>I', cali_coeff[index+5:index+9])[0]/1e6)
|
||||
# hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e5)
|
||||
# hsrtia_d.append(struct.unpack('>I', cali_coeff[index+13:index+17])[0]/1e6)
|
||||
index = 140
|
||||
g = 1
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 160
|
||||
g = 1
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 180
|
||||
g = 2
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 200
|
||||
g = 2
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 220
|
||||
g = 3
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 240
|
||||
g = 3
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
# print('cutoff_freq', cutoff_freq)
|
||||
# print('hsrtia_a', hsrtia_a)
|
||||
# print('hsrtia_b', hsrtia_b)
|
||||
# print('hsrtia_c', hsrtia_c)
|
||||
# print('hsrtia_d', hsrtia_d)
|
||||
# print('phase_para_a', phase_para_a)
|
||||
# print('phase_para_b', phase_para_b)
|
||||
# print('phase_coeff')
|
||||
# print(phase_coeff)
|
||||
# print('phase_offset')
|
||||
# print(phase_offset)
|
||||
|
||||
cali_table.append((cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
|
||||
cali_table.append((cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
|
||||
|
||||
return cali_table
|
||||
else:
|
||||
@@ -1462,7 +1527,7 @@ 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)
|
||||
gain = data[20+3]
|
||||
finishMode = (d19 & 0x80) >> 7
|
||||
|
||||
if time_stamp == 0:
|
||||
@@ -1472,7 +1537,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)
|
||||
@@ -1481,31 +1546,33 @@ 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
|
||||
cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
|
||||
|
||||
if (self._mode == 0):
|
||||
voltage_amp = round(self._ac_amp * 800 / 2047) # use UI value
|
||||
|
||||
if (self._mode == 0 or self._mode == 5):
|
||||
img = ch1
|
||||
real = ch2
|
||||
freq = ch3
|
||||
fre_idx = 0
|
||||
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2)
|
||||
# rolloff_cali = cutoff_freq/1e5
|
||||
rolloff_cali = hsrtia_c[gain]
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / rolloff_cali ** 2 / 1e4)
|
||||
|
||||
# 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]
|
||||
|
||||
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain]
|
||||
# current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
|
||||
|
||||
|
||||
# print(current)
|
||||
# print(voltage_mag)
|
||||
# print(hsrtia_a[gain])
|
||||
@@ -1518,64 +1585,64 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
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
|
||||
# last_phase_to90 = self._last_phase % 180 if self._last_phase % 180<=90 else self._last_phase % 180-180
|
||||
# diff = phase - last_phase_to90
|
||||
|
||||
# if (self._first_phase_flag):
|
||||
# # self._last_phase = phase
|
||||
# self._first_phase_flag = 0
|
||||
# elif (abs(diff) >= 90):
|
||||
# phase = self._last_phase + diff + (180 if diff<0 else-180)
|
||||
# else:
|
||||
# phase = self._last_phase + diff
|
||||
# self._last_phase = phase
|
||||
|
||||
imag_after_cal = impedance * math.sin(round(phase) * math.pi / 180)
|
||||
real_after_cal = impedance * math.cos(round(phase) * math.pi / 180)
|
||||
|
||||
|
||||
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
|
||||
if self._show_data:
|
||||
if (self._mode == 0 or self._mode == 5):
|
||||
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), '|', 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())
|
||||
@@ -1584,11 +1651,11 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
self._mode_stop = 0
|
||||
|
||||
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
|
||||
if (self._mode == 0): #EIS Mode
|
||||
ret.append_data(3, cycle_number)
|
||||
if self._mode == 0 or self._mode == 5: #EIS Mode
|
||||
ret.append_data(0, ch1) #Raw Imag
|
||||
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(6, round(impedance)) #Impedance [Ohm]
|
||||
@@ -1597,10 +1664,10 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
ret.append_data(9, gain) #Gain Level
|
||||
|
||||
else: #CV Mode
|
||||
ret.append_data(3, cycle_number)
|
||||
ret.append_data(0, ch1) #Iin [nA]
|
||||
ret.append_data(1, ch2) #Vset [nV]
|
||||
ret.append_data(2, ch3) #Vout [nV]
|
||||
ret.append_data(3, cycle_number)
|
||||
|
||||
if cycle_number != self._cycle_number:
|
||||
# notify cycle_number change
|
||||
|
||||
@@ -651,17 +651,9 @@ class DeviceInstruction:
|
||||
VIS_DEVICE_DONE = 0x20
|
||||
"""identify device done"""
|
||||
|
||||
VIS_CC_ZERO = 0x40
|
||||
|
||||
VIS_ASK = 0x30
|
||||
"""ask in virtual instruction"""
|
||||
|
||||
VIS_STI = 0xC0
|
||||
"""stimulation on virtual instruction"""
|
||||
|
||||
VIS_FUH = 0x90
|
||||
"""flush virtual instruction"""
|
||||
|
||||
VIS_INT = 0x60
|
||||
"""interrupt virtual instruction"""
|
||||
|
||||
@@ -732,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'
|
||||
|
||||
@@ -747,19 +738,15 @@ class DeviceCommonInstruction:
|
||||
elif instruction == cls.START:
|
||||
return '_data_format("TDC4VAF2")', '_notify(True)', 'VIS_STI', '_sync(True)'
|
||||
elif instruction == cls.INTERRUPT:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
return '_notify(False)', 'VIS_INT', '_sync(False)'
|
||||
elif instruction == cls.CLOSE:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
elif instruction == cls.FLUSH:
|
||||
return 'VIS_FUH',
|
||||
elif instruction == cls.CALL:
|
||||
return 'VIS_CAL',
|
||||
elif instruction == cls.VIS_DEVICE_DETECT:
|
||||
return 'VIS_DEVICE_DETECT',
|
||||
elif instruction == cls.VIS_DEVICE_DONE:
|
||||
return 'VIS_DEVICE_DONE',
|
||||
elif instruction == cls.VIS_CC_ZERO:
|
||||
return 'VIS_CC_ZERO',
|
||||
elif instruction == cls.RECORD:
|
||||
return 'VIS_STARTR',
|
||||
elif instruction == cls.RECORD_ALL:
|
||||
|
||||
@@ -4,6 +4,7 @@ from biopro.util.text import part_suffix
|
||||
from . import *
|
||||
from .expression import *
|
||||
|
||||
import json
|
||||
|
||||
class DeviceParameterError(RuntimeError):
|
||||
__slots__ = ()
|
||||
@@ -309,6 +310,8 @@ class ParameterValueDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
return f
|
||||
|
||||
def valid_para(self, value: Any) -> bool:
|
||||
if isinstance(value, list):
|
||||
return True
|
||||
f, t = self.range
|
||||
return f <= float(value) < t
|
||||
|
||||
@@ -489,8 +492,12 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
|
||||
@classmethod
|
||||
def parse(cls, expr: Union[int, str]) -> 'ParameterCollectionValueOperator':
|
||||
# parse epression then create value_operator
|
||||
if isinstance(expr, int):
|
||||
return SingleValueOperator(None, expr)
|
||||
|
||||
elif isinstance(expr, list):
|
||||
return CollectValueOperator((0, len(expr)), expr)
|
||||
|
||||
elif expr == '*':
|
||||
return AddAllValueOperator
|
||||
@@ -498,6 +505,10 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
elif expr == ':=':
|
||||
return CollectValueOperator((None, None), [])
|
||||
|
||||
elif '[' in expr and ']' in expr:
|
||||
v = json.loads(expr)
|
||||
return CollectValueOperator((0, len(v)), v)
|
||||
|
||||
elif '=' in expr:
|
||||
a, v = part_suffix(expr, '=')
|
||||
|
||||
@@ -508,6 +519,7 @@ class ParameterCollectionValueOperator(metaclass=abc.ABCMeta):
|
||||
return CollectValueOperator((None, None), v)
|
||||
|
||||
else:
|
||||
# get list length (old way)
|
||||
a, b = part_suffix(a, ':')
|
||||
a = int(a) if len(a) else None
|
||||
b = int(b) if len(b) else None
|
||||
@@ -602,8 +614,8 @@ class ParameterCollectionDomain(ParameterDomain, metaclass=abc.ABCMeta):
|
||||
def __init__(self, domain: ParameterDomain):
|
||||
super().__init__()
|
||||
|
||||
if isinstance(domain, ParameterCollectionDomain):
|
||||
raise RuntimeError('cannot compose with parameter collection domain')
|
||||
# if isinstance(domain, ParameterCollectionDomain):
|
||||
# raise RuntimeError('cannot compose with parameter collection domain')
|
||||
|
||||
self._domain = domain
|
||||
|
||||
@@ -725,6 +737,7 @@ class ParameterListDomain(ParameterCollectionDomain):
|
||||
if oper == AddAllValueOperator:
|
||||
raise ValueError("list parameter cannot accept '*' (all) value")
|
||||
|
||||
# d: domain, sz: lsit length, i: slice(a, b), v: list value
|
||||
d = self.element_domain
|
||||
sz = len(target)
|
||||
i = oper.index(sz)
|
||||
|
||||
@@ -119,7 +119,10 @@ class DeviceConfigurationEncoder:
|
||||
e.write(b'L\0')
|
||||
|
||||
else:
|
||||
parameter_type = cls._value_type(value[0])
|
||||
parameter_type = cls._value_type(max(value))
|
||||
for v in value:
|
||||
if isinstance(v, int) and v < 0:
|
||||
parameter_type = parameter_type.lower()
|
||||
e.write(b'L')
|
||||
e.write(parameter_type.encode())
|
||||
e.u8(sz)
|
||||
@@ -153,7 +156,8 @@ class DeviceConfigurationEncoder:
|
||||
if isinstance(value, bool):
|
||||
e.u8(1 if value else 0)
|
||||
|
||||
elif isinstance(value, str):
|
||||
elif isinstance(value, str) or isinstance(value, list):
|
||||
value = str(value)
|
||||
e.encode_string(value)
|
||||
|
||||
elif isinstance(value, int):
|
||||
@@ -170,7 +174,7 @@ class DeviceConfigurationEncoder:
|
||||
if isinstance(value, bool):
|
||||
return '?'
|
||||
|
||||
elif isinstance(value, str):
|
||||
elif isinstance(value, str) or isinstance(value, list):
|
||||
return 'p'
|
||||
|
||||
elif isinstance(value, int):
|
||||
|
||||
@@ -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')
|
||||
@@ -1268,14 +1270,15 @@ class InstructionTable(DictNode['Instruction']):
|
||||
instruction: str):
|
||||
"""call instruction. chain context with :class:`DeviceInternalInstructionScope`
|
||||
|
||||
:param master: master device
|
||||
:param device: device
|
||||
:param master: DeviceManager
|
||||
:param device: CompletedDevice
|
||||
:param context: scope
|
||||
:param instruction: instruction name
|
||||
:raises InstructionNotFound: If instruction not found.
|
||||
"""
|
||||
|
||||
try:
|
||||
# ex. start
|
||||
ins = self[instruction]
|
||||
|
||||
except KeyError as e:
|
||||
@@ -1284,6 +1287,7 @@ class InstructionTable(DictNode['Instruction']):
|
||||
else:
|
||||
context = context.chain(InstructionTableScope(self))
|
||||
|
||||
# ex. _data_format, _sync, _notify
|
||||
for single in ins.eval_instruction(context):
|
||||
if isinstance(single, InternalInstruction):
|
||||
if not single.handle_internal_instruction(master, device, context):
|
||||
|
||||
@@ -510,9 +510,10 @@ class DeviceParameter(JsonSerialize):
|
||||
:param para: parameter name
|
||||
:param oper: operator expression
|
||||
"""
|
||||
# parse operator return CollectValueOperator instance
|
||||
if not isinstance(oper, ParameterCollectionValueOperator):
|
||||
oper = ParameterCollectionValueOperator.parse(oper)
|
||||
|
||||
|
||||
table = self._library.parameter_table
|
||||
info = table[para]
|
||||
domain = info.domain
|
||||
@@ -528,6 +529,7 @@ class DeviceParameter(JsonSerialize):
|
||||
old = list(target)
|
||||
|
||||
try:
|
||||
# replace target with new oper
|
||||
domain.oper_para(target, oper, self._context)
|
||||
except RuntimeError as e:
|
||||
raise IllegalParameterValueError(para, str(oper)) from e
|
||||
@@ -966,7 +968,7 @@ class CompletedDevice(Device):
|
||||
"""
|
||||
__slots__ = ('_master', '_device_id', '_device', '_library', '_context',
|
||||
'_parameter', '_configuration', '_lock', '_feature_mask',
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff')
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project')
|
||||
|
||||
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
|
||||
"""
|
||||
@@ -976,11 +978,17 @@ class CompletedDevice(Device):
|
||||
:param device_id: device id
|
||||
:param device: slave device implementation
|
||||
"""
|
||||
# DeviceManager
|
||||
self._master = master
|
||||
self._device = device
|
||||
self._device_id = device_id
|
||||
self._library = library
|
||||
|
||||
# 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
|
||||
s2 = DeviceScope(self)
|
||||
@@ -1008,6 +1016,10 @@ class CompletedDevice(Device):
|
||||
def device_id(self) -> int:
|
||||
return self._device_id
|
||||
|
||||
@property
|
||||
def memory_board(self) -> int:
|
||||
return self._device_id
|
||||
|
||||
@property
|
||||
def device_name(self) -> str:
|
||||
return self._device.device_name
|
||||
@@ -1020,6 +1032,10 @@ class CompletedDevice(Device):
|
||||
def mac_address(self) -> ADDRESS:
|
||||
return self._device.mac_address
|
||||
|
||||
@property
|
||||
def mac_address_in_str(self) -> str:
|
||||
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address).upper()
|
||||
|
||||
@property
|
||||
def device(self) -> Device:
|
||||
return self._device
|
||||
@@ -1056,11 +1072,26 @@ class CompletedDevice(Device):
|
||||
return self._library
|
||||
|
||||
# device lock
|
||||
|
||||
@property
|
||||
def lock(self) -> DeviceLock:
|
||||
return self._lock
|
||||
|
||||
@property
|
||||
def status(self) -> int:
|
||||
return self._status
|
||||
|
||||
@status.setter
|
||||
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]:
|
||||
@@ -1084,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)
|
||||
@@ -1107,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
|
||||
@@ -1115,7 +1153,8 @@ class CompletedDevice(Device):
|
||||
self._master.log_warn('on_change instruction not found : ' + on_change)
|
||||
|
||||
else:
|
||||
self.call_instruction(on_change)
|
||||
if self._status == 1:
|
||||
self.call_instruction(on_change)
|
||||
|
||||
# device instruction call
|
||||
|
||||
@@ -1258,16 +1297,23 @@ class CompletedDevice(Device):
|
||||
|
||||
def as_json(self) -> JSON_OBJECT:
|
||||
return {
|
||||
'id': self.device_id,
|
||||
'name': self.device_name,
|
||||
'status': self._status,
|
||||
'device_id': self.device_id,
|
||||
'device_name': self.device_name,
|
||||
'device_address': list(self.mac_address),
|
||||
'device_status': self._status,
|
||||
'mac_address': self.mac_address_in_str,
|
||||
'memory_board': self.memory_board,
|
||||
'serial_number': self.serial_number.as_json(),
|
||||
'version': self.device_version,
|
||||
'battery': self.battery,
|
||||
'parent': self.parent,
|
||||
'recording_file_name': self.recording_file_name,
|
||||
'device_version': self.device_version,
|
||||
'serial_number': self.serial_number.as_json(),
|
||||
'library_name': self._library.name,
|
||||
'library_version': str(self._library.version),
|
||||
'occupied_by_project': self._occupied_by_project,
|
||||
'configuration': self.configuration.as_json(list_hide=True),
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
'_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value',
|
||||
'_read_green_times','_read_red_times',
|
||||
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
|
||||
'_head_wrong_cnt')
|
||||
'_head_wrong_cnt', '_pin_busy_value')
|
||||
|
||||
def __init__(self,
|
||||
select: Selector,
|
||||
@@ -50,11 +50,11 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
||||
|
||||
# buffer
|
||||
self._tx_buffer_header = [0] * 19
|
||||
self._tx_buffer_header = [0] * 64
|
||||
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
|
||||
|
||||
# memory control pin
|
||||
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True)
|
||||
self.pin_busy: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_BZY)
|
||||
self.pin_mem_req = OutputPin.get_used(P3Pin.MEM_REQ, False)
|
||||
self.pin_mem_sel = OutputPin.get_used(P3Pin.MEM_RST, True) # MEM_RST -> actually which memory board is assign
|
||||
self.pin_ram_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL) # MEM_SEL -> actually is RAM_SEL, which RAM is assign
|
||||
@@ -62,6 +62,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._pin_ram_sel_value = [bool(self.pin_ram_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_sel_value = [bool(self.pin_mem_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_req_value = [bool(self.pin_mem_req) for _ in range(Selector.SIZE)]
|
||||
self._pin_busy_value = [bool(self.pin_busy) for _ in range(Selector.SIZE)]
|
||||
|
||||
self._read_green_times = 0
|
||||
self._read_red_times = 0
|
||||
@@ -76,6 +77,8 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
def set_pin_mem_req(self, value: bool):
|
||||
channel = self.select
|
||||
# if self._pin_mem_req_value[channel] == value:
|
||||
# print('last_req_sig[channel] == value', channel, self._pin_mem_req_value[channel], value, datetime.now())
|
||||
self.pin_mem_req.output(value)
|
||||
self._pin_mem_req_value[channel] = value
|
||||
|
||||
@@ -96,6 +99,14 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._pin_ram_sel_value[channel] = True
|
||||
return self._pin_ram_sel_value[channel]
|
||||
|
||||
def get_pin_busy(self):
|
||||
channel = self.select
|
||||
if self.pin_busy.input() == 0:
|
||||
self._pin_busy_value[channel] = False
|
||||
else:
|
||||
self._pin_busy_value[channel] = True
|
||||
return self._pin_busy_value[channel]
|
||||
|
||||
@property
|
||||
def select(self) -> int:
|
||||
return self._selector.channel
|
||||
@@ -214,7 +225,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
return
|
||||
|
||||
def recv_memory(self, device: int) -> Optional[bytes]:
|
||||
self.pin_busy.output(False)
|
||||
# self.pin_busy.output(False)
|
||||
|
||||
# print('mem_req==ram_sel,[', self._pin_mem_req_value[device], ',', self._pin_ram_sel_value[device], ']')
|
||||
|
||||
rx = []
|
||||
|
||||
@@ -298,6 +311,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
print("green data print:", data, device, datetime.now())
|
||||
return None
|
||||
|
||||
# print('data=', list(data))
|
||||
# print('Ram:', data[62])
|
||||
|
||||
if (length >= 4000):
|
||||
flag_print = True
|
||||
print("green data: big length:", length)
|
||||
@@ -413,9 +429,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
|
||||
finally:
|
||||
# print("\n")
|
||||
self.pin_busy.output(True)
|
||||
# finally:
|
||||
# # print("\n")
|
||||
# self.pin_busy.output(True)
|
||||
|
||||
return bytes(rx)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -118,13 +118,13 @@ class Selector:
|
||||
self._p2.output(p[2])
|
||||
|
||||
# if (value == 4 and self._last_sel != 6):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
|
||||
# elif (value == 5 and self._last_sel != 4):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
|
||||
# elif (value == 7 and self._last_sel != 5):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
|
||||
# elif (value == 6 and self._last_sel != 7):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel, datetime.now())
|
||||
|
||||
self._last_sel = value
|
||||
|
||||
|
||||
@@ -1,68 +1,34 @@
|
||||
|
||||
class Action():
|
||||
def __init__(self, task, action_id, action):
|
||||
self._task = task
|
||||
self._id:str = action_id
|
||||
self._type:str = action['type']
|
||||
self._target:str = action['target']
|
||||
self._condition_list:list[str] = action['condition']
|
||||
self._duration = action.get('duration', None)
|
||||
self._goto = action.get('goto', None)
|
||||
self._cycle = action.get('cycle', None)
|
||||
self._instruction = None
|
||||
|
||||
self.update_instruction()
|
||||
def __init__(self, action_id, action):
|
||||
self._id: str = action_id
|
||||
self._type: str = action['type']
|
||||
self._target: str = action['target']
|
||||
self._condition : list[str] = action['condition']
|
||||
# self._duration = action.get('duration', None)
|
||||
# self._goto = action.get('goto', None)
|
||||
# self._cycle = action.get('cycle', None)
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
def update_instruction(self):
|
||||
instruction_type = self._type
|
||||
if instruction_type == 'stop':
|
||||
instruction_type = 'interrupt'
|
||||
|
||||
self._instruction = {
|
||||
"device_instruction": {
|
||||
"header": "call_instruction",
|
||||
"device": self._target,
|
||||
"arguments": {
|
||||
"instruction": instruction_type,
|
||||
}
|
||||
},
|
||||
"device_parameter": {
|
||||
"header": "set_multi_parameters",
|
||||
"device": self._target,
|
||||
"arguments": {
|
||||
"parameter": self._task.get_parameter_set_by_device(self._target),
|
||||
}
|
||||
},
|
||||
"device_recording_file_name": {
|
||||
"header": "update_recording_file_name_info",
|
||||
"device": self._target,
|
||||
"arguments": {
|
||||
"content": self._task.file_name,
|
||||
}
|
||||
},
|
||||
"device_parent": {
|
||||
"header": "update_parent_info",
|
||||
"device": self._target,
|
||||
"arguments": {
|
||||
"content": self._task.parent
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def target(self):
|
||||
return self._target
|
||||
|
||||
@property
|
||||
def condition(self):
|
||||
return self._condition
|
||||
|
||||
def as_json(self):
|
||||
return {
|
||||
'id': self._id,
|
||||
'type': self._type,
|
||||
'target': self._target,
|
||||
'condition': self._condition
|
||||
}
|
||||
|
||||
def get_condition_list(self):
|
||||
return self._condition_list
|
||||
|
||||
def get_instruction(self, value):
|
||||
return self._instruction[value]
|
||||
|
||||
def get_instruction_list(self):
|
||||
instruction_set = {
|
||||
'start': ['device_parent', 'device_recording_file_name', 'device_parameter', 'device_instruction'],
|
||||
'stop': ['device_instruction'],
|
||||
}
|
||||
|
||||
return map(self.get_instruction, instruction_set[self._type])
|
||||
|
||||
@@ -7,6 +7,7 @@ class Condition():
|
||||
self._type = condition['type']
|
||||
self._comparsion = condition['comparsion']
|
||||
self._value = condition['value']
|
||||
self._active = False
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
@@ -24,20 +25,28 @@ class Condition():
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
def set_comparsion(self, comparsion):
|
||||
self._comparsion = comparsion
|
||||
|
||||
def set_type(self, type):
|
||||
self._type = type
|
||||
@id.setter
|
||||
def id(self, new_id):
|
||||
self._id = new_id
|
||||
|
||||
def set_value(self, value):
|
||||
self._value = value
|
||||
@type.setter
|
||||
def type(self, new_type):
|
||||
self._type = new_type
|
||||
|
||||
def compareWith(self, operator:str, x, y) -> bool:
|
||||
@comparsion.setter
|
||||
def comparsion(self, new_comparsion):
|
||||
self._comparsion = new_comparsion
|
||||
|
||||
@value.setter
|
||||
def value(self, new_value):
|
||||
self._value = new_value
|
||||
|
||||
def compareWith(self, operator, x, y) -> bool:
|
||||
# print(operator, x, y)
|
||||
cases = {
|
||||
"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)
|
||||
@@ -47,37 +56,90 @@ class Condition():
|
||||
return getattr(self, self.type)(**kwargs)
|
||||
|
||||
def absolute_time(self, **kwargs):
|
||||
now = time()
|
||||
time_condition = self.datetime_to_timestamp(self.str_to_datetime(self._value))
|
||||
# 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, int(now), int(time_condition))
|
||||
return self.compareWith(self.comparsion, now, time_condition)
|
||||
|
||||
def relative_time(self, **kwargs):
|
||||
def after_project_run(self, **kwargs):
|
||||
project_start_time = kwargs['project_start_time']
|
||||
task_start_time = kwargs['task_start_time']
|
||||
delay_time = kwargs['delay_time']
|
||||
now = time()
|
||||
|
||||
time_diff = int(now - 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['task_start_time'],kwargs['delay_time'])
|
||||
if len(kwargs['task_start_time']) == 0:
|
||||
return False
|
||||
task = kwargs['self_task']
|
||||
running_task = kwargs['running_task']
|
||||
task_start_time = kwargs['task_start_time'][-1]
|
||||
delay_time = kwargs['delay_time']
|
||||
|
||||
time_diff = round(time() - task_start_time - delay_time, 1)
|
||||
# print('real_diff', time() - task_start_time - delay_time)
|
||||
# print(task.name, task.uuid, time_diff, round(int(self._value), 1), running_task.name, running_task.uuid)
|
||||
# if round(int(self._value), 1) == 0 and time_diff == 0.1:
|
||||
# return True
|
||||
if task.uuid != running_task.uuid:
|
||||
return False
|
||||
return self.compareWith('bigger', time_diff, round(int(self._value), 1))
|
||||
# return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
|
||||
|
||||
def device(self, **kwargs):
|
||||
print('device')
|
||||
|
||||
def task_status(self, **kwargs):
|
||||
print('task_status')
|
||||
""" 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 method_mapping(self, method_name):
|
||||
methods = {
|
||||
"relative_time": self.relative_time,
|
||||
"absolute_time": self.absolute_time,
|
||||
"device": self.device,
|
||||
"task_status": self.task_status,
|
||||
}
|
||||
return methods[method_name]
|
||||
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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
class Instruction():
|
||||
def __init__(self):
|
||||
self._instruction_set = {
|
||||
'set_file_name': {
|
||||
'method': 'update_recording_file_name_info',
|
||||
'arguments': ['file_name']
|
||||
},
|
||||
'set_parent': {
|
||||
'method': 'update_parent_info',
|
||||
'arguments': ['parent']
|
||||
},
|
||||
'set_parameter':{
|
||||
'method': 'set_multi_parameters',
|
||||
'arguments': ['parameter']
|
||||
},
|
||||
'call_instruction': {
|
||||
'method': 'call_instruction',
|
||||
'arguments': ['instruction']
|
||||
},
|
||||
}
|
||||
|
||||
self._start_instruction = list(map(lambda ins: self._instruction_set[ins] ,['set_file_name', 'set_parent', 'set_parameter', 'call_instruction']))
|
||||
self._stop_instruction = list(map(lambda ins: self._instruction_set[ins] ,['call_instruction']))
|
||||
self._idle_instruction = []
|
||||
|
||||
@property
|
||||
def start(self) -> list:
|
||||
return self._start_instruction
|
||||
|
||||
@property
|
||||
def stop(self) -> list:
|
||||
return self._stop_instruction
|
||||
|
||||
@property
|
||||
def idle(self) -> list:
|
||||
return self.idle_instruction
|
||||
@@ -1,82 +1,378 @@
|
||||
from .task import Task
|
||||
from .task_manager import TaskManager
|
||||
import sys
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
import logging
|
||||
|
||||
from time import time, sleep
|
||||
from datetime import datetime
|
||||
from collections import deque
|
||||
from copy import copy
|
||||
from uuid import uuid4
|
||||
|
||||
from .task import Task
|
||||
from .task_manager import TaskManager
|
||||
from .instruction import Instruction
|
||||
from biopro.device.manager import DeviceManager
|
||||
from biopro.text import *
|
||||
from copy import copy
|
||||
|
||||
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
|
||||
|
||||
self._task_manager = TaskManager(self._project['taskList'])
|
||||
self._stop = False
|
||||
self._id = None
|
||||
self._uuid = str(uuid4())
|
||||
self._name = None
|
||||
self._desc = None
|
||||
self._device = None
|
||||
self._complete_device = {}
|
||||
self._status = 0
|
||||
|
||||
self._instruction_set = Instruction()
|
||||
self._stop_flag = False
|
||||
|
||||
self._task_manager = None
|
||||
|
||||
self._cycle = []
|
||||
|
||||
self._count = 1 #流水號
|
||||
|
||||
self.log_verbose = log_verbose
|
||||
self._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'{self.uuid}.log', mode="w")
|
||||
fh.setFormatter(self._formatter)
|
||||
self._logger.addHandler(fh)
|
||||
|
||||
def setup_project(self, project):
|
||||
for (key, value) in project.items():
|
||||
if key in key_list.keys():
|
||||
key = key_list[key]
|
||||
|
||||
if key == 'task':
|
||||
self._task_manager = TaskManager(project['task'], project['cycle'])
|
||||
elif key == 'uuid':
|
||||
pass
|
||||
else:
|
||||
setattr(self, key, value)
|
||||
|
||||
def setup_device(self, device_list):
|
||||
for device in device_list:
|
||||
mac_address = device_list[device]['pair']
|
||||
complete_device = self._device_manager.get_device(mac_address)
|
||||
complete_device.occupied_by_project = self._uuid
|
||||
self._complete_device[device] = complete_device
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@id.setter
|
||||
def id(self, new_id):
|
||||
self._id = new_id
|
||||
|
||||
@property
|
||||
def uuid(self) -> str:
|
||||
return self._uuid
|
||||
|
||||
@uuid.setter
|
||||
def uuid(self, new_uuid):
|
||||
self._uuid = new_uuid
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, new_name):
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def cycle(self) -> list:
|
||||
return self._cycle
|
||||
|
||||
@cycle.setter
|
||||
def cycle(self, new_cycle):
|
||||
self._cycle = new_cycle
|
||||
|
||||
@property
|
||||
def desc(self) -> str:
|
||||
return self._project['desc']
|
||||
return self._desc
|
||||
|
||||
@desc.setter
|
||||
def desc(self, new_desc):
|
||||
self._desc = new_desc
|
||||
|
||||
@property
|
||||
def status(self) -> str:
|
||||
return self._project['status']
|
||||
return self._status
|
||||
|
||||
@status.setter
|
||||
def status(self, new_status):
|
||||
self._status = new_status
|
||||
|
||||
@property
|
||||
def device(self) -> list:
|
||||
return self._project['deviceList']
|
||||
return self._device
|
||||
|
||||
@device.setter
|
||||
def device(self, new_device):
|
||||
self._device = new_device
|
||||
|
||||
@property
|
||||
def task_list(self):
|
||||
return self._task_manager.export_task_list
|
||||
|
||||
@property
|
||||
def task(self) -> list:
|
||||
return self._task_manager.get()
|
||||
def mqtt_thread(self):
|
||||
return self._mqtt_thread
|
||||
|
||||
@property
|
||||
def get_current_task(self) -> str:
|
||||
return self._task_manager.get_current_task()
|
||||
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):
|
||||
self._start_time = time.time()
|
||||
# project status change running (1)
|
||||
self._status = 1
|
||||
# save start time
|
||||
self._start_time = time()
|
||||
|
||||
while not self._stop:
|
||||
# current task
|
||||
task_check_list = copy(self._task_manager.get_check_task_list())
|
||||
# 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 :
|
||||
# check running task first
|
||||
delay_time = 0
|
||||
for task in task_check_list:
|
||||
# [<match_condition>, ...]
|
||||
match_condition_list = task.check_condition(project_start_time = self._start_time, delay_time = delay_time)
|
||||
# [[<match_action>, ...], ...]
|
||||
match_action_list = task.get_match_action_list(match_condition_list)
|
||||
|
||||
for action_list in match_action_list:
|
||||
for action in action_list:
|
||||
if action.type == 'start':
|
||||
task.reset_start_time()
|
||||
self._task_manager.set_current_task(task)
|
||||
task.do_action(action)
|
||||
|
||||
now = time.time()
|
||||
while len(task.instruction_list) > 0:
|
||||
instruction = task.instruction_list.pop(0)
|
||||
if instruction.get('device', None) != None:
|
||||
device = self._device_manager.get_device(self.device[instruction['device']]['connectDevice']['device_address'])
|
||||
check_list = copy(self._task_manager.check_list)
|
||||
|
||||
if device is None:
|
||||
raise RuntimeError(DEVICE_NOT_FOUND, device)
|
||||
for task in check_list:
|
||||
if task != None:
|
||||
now = time()
|
||||
|
||||
getattr(device, instruction['header'])(*instruction['arguments'].values())
|
||||
delay_time += (time.time() - now)
|
||||
time.sleep(self._time_interval)
|
||||
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,
|
||||
self_task = task
|
||||
)
|
||||
|
||||
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:
|
||||
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"]} -----------')
|
||||
|
||||
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:
|
||||
if action.type == 'start':
|
||||
self._count += 1
|
||||
for instruction in instruction_set:
|
||||
print('instruction 1', device, instruction, datetime.now())
|
||||
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
|
||||
target=getattr(device, instruction['method'])(*args)
|
||||
print('instruction 2', device, instruction, datetime.now())
|
||||
|
||||
delay_time += (time() - now)
|
||||
|
||||
# check task not running then stop
|
||||
if self.check_running_task_not_run() == True:
|
||||
# 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.stop()
|
||||
|
||||
if self._time_interval - delay_time > 0:
|
||||
sleep(self._time_interval - delay_time)
|
||||
|
||||
def pause(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
self._stop = True
|
||||
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):
|
||||
self._stop = True
|
||||
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
|
||||
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
|
||||
def check_project_done(self):
|
||||
for task in self._task_manager.task_list:
|
||||
# if task never start or still task is running then reject
|
||||
if task.status == 1 or task.status == -1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_content(self, content):
|
||||
self.running_task.button_trigger = True
|
||||
|
||||
def set_cycle(self, index, content):
|
||||
# change cycle name
|
||||
for key in content:
|
||||
self.cycle[index][key] = content[key]
|
||||
|
||||
# change task name
|
||||
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][0]).name = content['name']
|
||||
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][1]).name = content['name']
|
||||
|
||||
def check_running_task_not_run(self):
|
||||
# if no running task
|
||||
if self._task_manager.running_task == None:
|
||||
return False
|
||||
|
||||
# if running is cycle then no need to stop by device
|
||||
if self._task_manager.running_task.type == 'cycle':
|
||||
return False
|
||||
|
||||
for key in self._task_manager.running_task.action:
|
||||
# print('action key', key, self._task_manager.running_task, self._task_manager.running_task.action[key])
|
||||
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'stop':
|
||||
return False
|
||||
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'idle':
|
||||
return False
|
||||
|
||||
for device in self._task_manager.running_task.device:
|
||||
if self._complete_device[device].status == 1:
|
||||
return False
|
||||
return True
|
||||
|
||||
def as_json(self):
|
||||
running_task = None
|
||||
if self._task_manager.running_task is not None:
|
||||
running_task = self._task_manager.running_task.as_json()
|
||||
data = {
|
||||
'id': self._id,
|
||||
'name': self._name,
|
||||
'uuid': self._uuid,
|
||||
'desc': self._desc,
|
||||
'status': self._status,
|
||||
'device': self._device,
|
||||
'task': self.task_list,
|
||||
'running_task': running_task,
|
||||
'cycle': self._cycle,
|
||||
'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,25 +9,40 @@ 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
|
||||
|
||||
|
||||
def remove(self, index):
|
||||
self._project_list[index].stop()
|
||||
del self._project_list[index]
|
||||
|
||||
def get(self):
|
||||
return self._project_list
|
||||
def get(self, project_uuid = None):
|
||||
if project_uuid == None:
|
||||
return self._project_list
|
||||
else:
|
||||
for project in self._project_list:
|
||||
if project.uuid == project_uuid:
|
||||
return project
|
||||
|
||||
def run(self, project):
|
||||
def run_project(self, project):
|
||||
project.start()
|
||||
|
||||
def stop(self, project):
|
||||
project.stop()
|
||||
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)
|
||||
|
||||
+259
-116
@@ -2,112 +2,237 @@ from typing import List
|
||||
from .condition import Condition
|
||||
from .action import Action
|
||||
from time import time
|
||||
from datetime import datetime
|
||||
|
||||
key_list = {
|
||||
'deviceList': 'device',
|
||||
'parameterSet': 'parameter_set'
|
||||
}
|
||||
|
||||
class Task:
|
||||
def __init__(self, task):
|
||||
self._task = task
|
||||
|
||||
self._condition_list:List[Condition] = []
|
||||
self._action_list:List[Action] = []
|
||||
|
||||
self._start_time = time()
|
||||
self._idle_time = []
|
||||
self._period = None
|
||||
self._next_time = None
|
||||
self._last_time = None
|
||||
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: 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.setup()
|
||||
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 setup(self) -> None:
|
||||
# add condition
|
||||
for key, condition in self._task['condition'].items():
|
||||
new_condition = Condition(key, condition)
|
||||
self._condition_list.append(new_condition)
|
||||
def load_task(self, task) -> None:
|
||||
# update task attribute
|
||||
for key, value in task.items():
|
||||
if key in key_list.keys():
|
||||
key = key_list[key]
|
||||
if key == 'condition':
|
||||
self.update_condition_list(value)
|
||||
if key == 'action':
|
||||
self.update_action_list(value)
|
||||
# print(key, value)
|
||||
setattr(self, key, value)
|
||||
|
||||
# add action
|
||||
for key, action in self._task['action'].items():
|
||||
new_action = Action(self, key, action)
|
||||
self._action_list.append(new_action)
|
||||
def update_condition_list(self, condition_dict):
|
||||
self._condition_list.clear()
|
||||
for key, condition in condition_dict.items():
|
||||
self._condition_list.append(Condition(key, condition))
|
||||
|
||||
def update_action_list(self, action_dict):
|
||||
self._action_list.clear()
|
||||
for key, action in action_dict.items():
|
||||
self._action_list.append(Action(key, action))
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return self._task['id']
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def file_name(self):
|
||||
return self._task['name']
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
return self._task.get('parent', {"folder": [2]})
|
||||
|
||||
@property
|
||||
def instruction_list(self):
|
||||
return self._instruction_list
|
||||
|
||||
@property
|
||||
def cycle(self) -> int:
|
||||
return self._task['cycle']
|
||||
|
||||
@property
|
||||
def order(self) -> int:
|
||||
return self._task['order']
|
||||
|
||||
@property
|
||||
def max_cycle(self) -> int:
|
||||
return self._task['max_cycle']
|
||||
|
||||
@property
|
||||
def devices(self) -> dict:
|
||||
return self._task['devices']
|
||||
|
||||
@property
|
||||
def devices_id(self) -> list:
|
||||
return [device_id for device_id in self.devices]
|
||||
|
||||
@property
|
||||
def events(self) -> list:
|
||||
return self._task['events']
|
||||
|
||||
@property
|
||||
def triggers(self) -> list:
|
||||
return self._task['triggers']
|
||||
|
||||
@property
|
||||
def parameter_set(self) -> list:
|
||||
return self._task['parameterSet']
|
||||
|
||||
@property
|
||||
def instructions(self) -> list:
|
||||
return self._task['instructions']
|
||||
|
||||
@property
|
||||
def conditions(self) -> list:
|
||||
return self._task['conditions']
|
||||
|
||||
@property
|
||||
def actions(self) -> list:
|
||||
return self._task['actions']
|
||||
|
||||
@property
|
||||
def condition_list(self) -> list:
|
||||
return self._condition_list
|
||||
|
||||
@property
|
||||
def status(self) -> str:
|
||||
return self._task['status']
|
||||
@id.setter
|
||||
def id(self, new_id):
|
||||
self._id = new_id
|
||||
|
||||
@property
|
||||
def uuid(self) -> str:
|
||||
return self._task['uuid']
|
||||
return self._uuid
|
||||
|
||||
@uuid.setter
|
||||
def uuid(self, new_uuid):
|
||||
self._uuid = new_uuid
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@type.setter
|
||||
def type(self, new_type):
|
||||
self._type = new_type
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@name.setter
|
||||
def name(self, new_name):
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def parent(self):
|
||||
if self._parent == None:
|
||||
return {"folder": [2]}
|
||||
return self._parent
|
||||
|
||||
@parent.setter
|
||||
def parent(self, new_parent):
|
||||
self._parent = new_parent
|
||||
|
||||
@property
|
||||
def cycle(self) -> int:
|
||||
return self._cycle
|
||||
|
||||
@cycle.setter
|
||||
def cycle(self, new_cycle):
|
||||
self._cycle = new_cycle
|
||||
|
||||
# TODO: not sure needed?
|
||||
@property
|
||||
def cycle_count(self) -> int:
|
||||
return self._cycle_count
|
||||
|
||||
@cycle_count.setter
|
||||
def cycle_count(self, new_cycle_count):
|
||||
self._cycle_count = new_cycle_count
|
||||
|
||||
@property
|
||||
def cycle_next(self) -> str:
|
||||
return self._cycle_next
|
||||
|
||||
@cycle_next.setter
|
||||
def cycle_next(self, new_cycle_next):
|
||||
self._cycle_next = new_cycle_next
|
||||
|
||||
@property
|
||||
def cycle_next_uuid(self) -> str:
|
||||
return self._cycle_next_uuid
|
||||
|
||||
@cycle_next_uuid.setter
|
||||
def cycle_next_uuid(self, new_cycle_next_uuid):
|
||||
self._cycle_next_uuid = new_cycle_next_uuid
|
||||
|
||||
@property
|
||||
def device(self) -> dict:
|
||||
return self._device
|
||||
|
||||
@device.setter
|
||||
def device(self, new_device):
|
||||
self._device = new_device
|
||||
|
||||
@property
|
||||
def event(self) -> list:
|
||||
return self._event
|
||||
|
||||
@event.setter
|
||||
def event(self, new_event):
|
||||
self._event = new_event
|
||||
|
||||
@property
|
||||
def trigger(self) -> list:
|
||||
return self._trigger
|
||||
|
||||
@trigger.setter
|
||||
def trigger(self, new_trigger):
|
||||
self._trigger = new_trigger
|
||||
|
||||
@property
|
||||
def parameter_set(self) -> list:
|
||||
return self._parameter_set
|
||||
|
||||
@parameter_set.setter
|
||||
def parameter_set(self, new_parameter_set):
|
||||
self._parameter_set = new_parameter_set
|
||||
|
||||
@property
|
||||
def condition(self) -> list:
|
||||
return self._condition
|
||||
|
||||
@condition.setter
|
||||
def condition(self, new_condition):
|
||||
self._condition = new_condition
|
||||
|
||||
@property
|
||||
def action(self) -> list:
|
||||
return self._action
|
||||
|
||||
@action.setter
|
||||
def action(self, new_action):
|
||||
self._action = new_action
|
||||
|
||||
@property
|
||||
def status(self) -> str:
|
||||
return self._status
|
||||
|
||||
@status.setter
|
||||
def status(self, new_status):
|
||||
self._status = new_status
|
||||
|
||||
@property
|
||||
def next(self) -> str:
|
||||
return self._task['next']
|
||||
return self._next
|
||||
|
||||
def reset_start_time(self):
|
||||
self._start_time = time()
|
||||
@next.setter
|
||||
def next(self, new_next):
|
||||
self._next = new_next
|
||||
|
||||
@property
|
||||
def instruction_list(self) -> List:
|
||||
return self._instruction_list
|
||||
|
||||
@property
|
||||
def start_time(self) -> List:
|
||||
return self._start_time
|
||||
|
||||
@property
|
||||
def end_time(self) -> List:
|
||||
return self._end_time
|
||||
|
||||
@property
|
||||
def button_trigger(self) -> List:
|
||||
return self._button_trigger
|
||||
|
||||
@button_trigger.setter
|
||||
def button_trigger(self, button_trigger):
|
||||
self._button_trigger = button_trigger
|
||||
|
||||
def new_start_time(self):
|
||||
self._start_time.append(time())
|
||||
|
||||
def new_end_time(self):
|
||||
self._end_time.append(time())
|
||||
|
||||
def get_parameter_set_by_device(self, device):
|
||||
return [parameter_set for parameter_set in self.parameter_set.values() if device == parameter_set['target']]
|
||||
@@ -124,46 +249,64 @@ class Task:
|
||||
return '|'.join(name_list) if name_or_value == 'name' else '|'.join(value_list)
|
||||
|
||||
def run(self):
|
||||
self._status = 'running'
|
||||
self._start_time = time()
|
||||
|
||||
def pause(self):
|
||||
self._status = 'pause'
|
||||
|
||||
def set_cycle(self, cycle):
|
||||
self._cycle = cycle
|
||||
|
||||
def set_status(self, status):
|
||||
self._status = status
|
||||
print(self._name, 'run at', datetime.now())
|
||||
self._status = 1
|
||||
self._start_time.append(time())
|
||||
|
||||
def start(self):
|
||||
self.set_status('running')
|
||||
self.status = 1
|
||||
|
||||
def stop(self):
|
||||
if self.status == 'running':
|
||||
self.do_action('stop')
|
||||
self.set_status('idle')
|
||||
|
||||
def done(self):
|
||||
self.set_status('done')
|
||||
self.status = 2
|
||||
|
||||
def end(self):
|
||||
self.set_status('end')
|
||||
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)
|
||||
|
||||
def get_match_action(self, condition_id):
|
||||
return [action for action in self._action_list if condition_id in action.condition]
|
||||
|
||||
def do_action(self, action):
|
||||
for instruction in action.get_instruction_list():
|
||||
self._instruction_list.append(instruction)
|
||||
|
||||
def status_mapping(self, status):
|
||||
statuses = {
|
||||
"start": self.task_start,
|
||||
"done": self.task_done,
|
||||
}
|
||||
return statuses[status]
|
||||
|
||||
def check_condition(self, **kwargs):
|
||||
kwargs['task_start_time'] = self._start_time
|
||||
return [condition for condition in self._condition_list if condition.match_or_not(**kwargs)]
|
||||
return [condition for condition in self._condition_list if condition.match_or_not(**kwargs)]
|
||||
|
||||
def get_task_info(self, action):
|
||||
_type = action.type
|
||||
if _type == 'stop':
|
||||
_type = 'interrupt'
|
||||
|
||||
return {
|
||||
'device': action.target,
|
||||
'parameter': self.get_parameter_set_by_device(action.target),
|
||||
'file_name': self._name,
|
||||
'parent': self.parent,
|
||||
'instruction': _type
|
||||
}
|
||||
|
||||
def as_json(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'parent': self.parent,
|
||||
'type': self.type,
|
||||
'uuid': self.uuid,
|
||||
'cycle': self.cycle,
|
||||
'cycle_count': self.cycle_count,
|
||||
'cycle_next': self.cycle_next,
|
||||
'cycle_next_uuid': self.cycle_next_uuid,
|
||||
'device': self.device,
|
||||
'event': self.event,
|
||||
'trigger': self.trigger,
|
||||
'parameter_set': self.parameter_set,
|
||||
'condition': self.condition,
|
||||
'action': self.action,
|
||||
'status': self.status,
|
||||
'next': self.next,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from json import loads as json_parse, dumps as _json_stringify
|
||||
from socket import if_nametoindex
|
||||
from typing import Dict, List, Optional, Any
|
||||
from xml.dom.expatbuilder import parseString
|
||||
import paho.mqtt.client as mqtt
|
||||
@@ -11,46 +12,154 @@ def json_stringify(o: Any) -> str:
|
||||
return _json_stringify(o, separators=(',', ':'))
|
||||
|
||||
class TaskManager():
|
||||
def __init__(self, task_list):
|
||||
self._current_task = None
|
||||
def __init__(self, task_list, cycle_list):
|
||||
self._task_list = []
|
||||
self._need_to_check_task_list = []
|
||||
self._next_task = []
|
||||
self._prev_task = None
|
||||
self._running_task = None
|
||||
self._cycle_list = cycle_list
|
||||
|
||||
self.load_task_list(task_list)
|
||||
|
||||
# self.set_running_task(self._task_list[0])
|
||||
# self._running_task.run()
|
||||
self._next_task.append(self._task_list[0])
|
||||
|
||||
@property
|
||||
def task_list(self):
|
||||
return self._task_list
|
||||
|
||||
@property
|
||||
def export_task_list(self):
|
||||
return [d.as_json() for d in self._task_list]
|
||||
|
||||
@property
|
||||
def prev_task(self):
|
||||
return self._prev_task
|
||||
|
||||
@property
|
||||
def running_task(self):
|
||||
return self._running_task
|
||||
|
||||
@property
|
||||
def next_task(self):
|
||||
return self._next_task
|
||||
|
||||
def get_task_by_index(self, index):
|
||||
return self._task_list[index]
|
||||
|
||||
def get_task_by_uuid(self, uuid):
|
||||
return next((x for x in self.task_list if x.uuid == uuid), None)
|
||||
|
||||
def get_index_by_task(self, task):
|
||||
return next((i for i, x in enumerate(self.task_list) if x.uuid == task.uuid), None)
|
||||
|
||||
def get_index_by_uuid(self, uuid):
|
||||
return next((i for i, x in enumerate(self.task_list) if x.uuid == uuid), None)
|
||||
|
||||
def check_task_is_cycle_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
|
||||
|
||||
@property
|
||||
def check_list(self):
|
||||
return [self._running_task, *self._next_task]
|
||||
|
||||
@property
|
||||
def check_list(self):
|
||||
return [self._running_task, *self._next_task]
|
||||
|
||||
def load_task_list(self, task_list):
|
||||
for task in task_list:
|
||||
task = Task(task)
|
||||
self._task_list.append(task)
|
||||
|
||||
self.set_current_task(self._task_list[0])
|
||||
self._current_task.run()
|
||||
|
||||
def remove(self, index):
|
||||
pass
|
||||
# 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:
|
||||
return False
|
||||
|
||||
# save running task
|
||||
self._prev_task = self._running_task
|
||||
# clear next task list
|
||||
self._next_task.clear()
|
||||
self._running_task = task
|
||||
self._running_task.run()
|
||||
|
||||
if self._prev_task != None:
|
||||
# if previous task is still running, then need to close
|
||||
if self._prev_task.status == 1:
|
||||
self._prev_task.stop()
|
||||
print('prev', 'run', self._prev_task.name, self._running_task.name)
|
||||
|
||||
for task_uuid in self._running_task.next:
|
||||
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
|
||||
if _task != None:
|
||||
self._next_task.append(_task)
|
||||
except RuntimeError as e:
|
||||
print(e) """
|
||||
|
||||
def set_running_task(self, task):
|
||||
try:
|
||||
# if there is task running & same task active ,then reject
|
||||
if self._running_task != None and self._running_task.uuid == task.uuid:
|
||||
return False
|
||||
|
||||
# save task
|
||||
self._prev_task = self._running_task
|
||||
# clear next task list
|
||||
self._next_task.clear()
|
||||
# set task to running_task
|
||||
self._running_task = task
|
||||
self._running_task.run()
|
||||
|
||||
# if previous task is still running, then need to close
|
||||
if self._prev_task != None:
|
||||
if self._prev_task.status == 1:
|
||||
self._prev_task.stop()
|
||||
# if reach cycle end, count < max, then go to cycle start
|
||||
cycle_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 get_check_task_list(self) -> List[Task]:
|
||||
return self._need_to_check_task_list
|
||||
|
||||
def get_current_task(self) -> Task:
|
||||
return self._current_task
|
||||
|
||||
def get_next_task(self):
|
||||
return self._current_task.next
|
||||
|
||||
def set_current_task(self, task):
|
||||
try:
|
||||
if self._current_task != None and self._current_task.id != task.id:
|
||||
self._current_task.stop()
|
||||
|
||||
self._current_task = task
|
||||
self._need_to_check_task_list = []
|
||||
# append current task
|
||||
self._need_to_check_task_list.append(self._current_task)
|
||||
|
||||
# append next task
|
||||
for task_uuid in self._current_task.next:
|
||||
task = next((task for task in self._task_list if task.uuid == task_uuid), None)
|
||||
self._need_to_check_task_list.append(task)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -104,18 +102,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
self.log_verbose,
|
||||
'MQTT-data-server')
|
||||
# api socket
|
||||
self._queue_spi = queue.Queue()
|
||||
# self._queue_spi_dict = {}
|
||||
self._queue_ds_dict = {}
|
||||
self._queue_db = Queue()
|
||||
self._queue_db_error = Queue()
|
||||
# self._queue_ds = Queue()
|
||||
|
||||
# if len(self._queue_spi_dict) == 0:
|
||||
# self._queue_spi_dict[4] = Queue()
|
||||
# self._queue_spi_dict[5] = Queue()
|
||||
# self._queue_spi_dict[6] = Queue()
|
||||
# self._queue_spi_dict[7] = Queue()
|
||||
self._queue_msg = Queue()
|
||||
|
||||
if len(self._queue_ds_dict) == 0:
|
||||
self._queue_ds_dict[4] = Queue()
|
||||
@@ -123,9 +112,12 @@ class DataServer(SocketServer, DataAPI):
|
||||
self._queue_ds_dict[6] = Queue()
|
||||
self._queue_ds_dict[7] = Queue()
|
||||
|
||||
self.database_process = DataBaseProcess('data_server', self.log_verbose, self._queue_db, self._queue_ds_dict, self._queue_db_error)
|
||||
self.database_process = DataBaseProcess('data_server', self.log_verbose, self._queue_db, self._queue_ds_dict, self._queue_msg)
|
||||
self.database_process.start()
|
||||
|
||||
# self._no_data_total_duration = 0
|
||||
# self._recv_memory_cost_time = 0
|
||||
|
||||
@logging_info
|
||||
def setup(self):
|
||||
self._available_channel.clear()
|
||||
@@ -146,7 +138,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
try:
|
||||
self._stop_runtime()
|
||||
self.stop_sync()
|
||||
self._queue_spi.queue.clear()
|
||||
finally:
|
||||
self._configurations.clear()
|
||||
|
||||
@@ -185,9 +176,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
|
||||
self._configurations.clear()
|
||||
|
||||
with CacheClient() as client:
|
||||
client.clear()
|
||||
|
||||
# reopen spi, which has close at close()
|
||||
if spi_mode is None:
|
||||
spi_mode = self._spi_mode
|
||||
@@ -327,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
|
||||
@@ -355,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']
|
||||
@@ -364,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 = result[1]
|
||||
|
||||
# while len(self._configurations) <= device_id:
|
||||
# self._configurationsappend(None)
|
||||
|
||||
@@ -390,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
|
||||
@@ -416,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)], meta_file,
|
||||
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)
|
||||
|
||||
@@ -618,8 +616,18 @@ class DataServer(SocketServer, DataAPI):
|
||||
return
|
||||
|
||||
def open_cache_client(self):
|
||||
self._cache_client = None
|
||||
return
|
||||
self.log_verbose('open cache client')
|
||||
try:
|
||||
client = CacheClient()
|
||||
client.open_socket()
|
||||
|
||||
except RuntimeError as e:
|
||||
self.log_warn(e)
|
||||
|
||||
else:
|
||||
client.clear()
|
||||
|
||||
self._cache_client = client
|
||||
|
||||
def _ensure_cache_client(self) -> Optional[CacheClient]:
|
||||
if self._cache_client is None:
|
||||
@@ -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,29 +674,49 @@ class DataServer(SocketServer, DataAPI):
|
||||
|
||||
else:
|
||||
data = None
|
||||
print('data=None, mem_req!=ram_sel, [', sync.get_pin_mem_req(), ', ', sync.get_pin_ram_sel(), ']', device, datetime.now())
|
||||
|
||||
if data is not None:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
ret = True
|
||||
if self._configurations.get(device, None) != None:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
if self._configurations.get(device, None) != None:
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
# self._no_data_total_duration = 0
|
||||
ret = True
|
||||
# else:
|
||||
# time_diff = time() - self._recv_memory_cost_time
|
||||
# self._no_data_total_duration += time_diff
|
||||
# if self._no_data_total_duration > 1:
|
||||
# print('data is None', device, datetime.now(), self._no_data_total_duration)
|
||||
# print("sync.get_pin_mem_req() != sync.get_pin_ram_sel()")
|
||||
# print("no~", sync.select, sync.get_pin_mem_req(), sync.get_pin_ram_sel(), datetime.now())
|
||||
# print()
|
||||
# self._recv_memory_cost_time = time()
|
||||
|
||||
return ret
|
||||
|
||||
def rec_update(self) -> bool:
|
||||
|
||||
device_id = self._queue_db_error.get()
|
||||
self.mqtt_thread.broadcast_command('runtime error: ' + str(device_id))
|
||||
content = {
|
||||
'header': 'device_instruction/0',
|
||||
'device': device_id,
|
||||
'instruction': 'interrupt'
|
||||
}
|
||||
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True)
|
||||
ds_db_msg = self._queue_msg.get()
|
||||
with CacheClient() as client:
|
||||
if isinstance(ds_db_msg, List):
|
||||
if ds_db_msg[0] == 'ds':
|
||||
client.send_command('device_instruction', ds_db_msg[1], ds_db_msg[2])
|
||||
else:
|
||||
self.mqtt_thread.broadcast_command('runtime error: ' + str(ds_db_msg))
|
||||
content = {
|
||||
'header': 'device_instruction/0',
|
||||
'device': ds_db_msg,
|
||||
'instruction': 'interrupt'
|
||||
}
|
||||
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',
|
||||
|
||||
@@ -69,7 +69,8 @@ class DataBaseProcess(Process):
|
||||
|
||||
self._data_raw_create_sql_str = None
|
||||
self._data_raw_update_sql_str = None
|
||||
self._data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s), end_time=%s, size=%s where id = %s'
|
||||
self._data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s) where id = %s'
|
||||
self._new_data_raw_recording_sql_str = 'UPDATE "public"."%s_recording_data_raws" SET data = concat(data, %s), end_time=%s, size=%s where id = %s'
|
||||
self._data_mini_recording_sql_str = 'UPDATE "public"."%s_recording_data_minis" SET data_mean = concat(data_mean, %s) where id = %s'
|
||||
|
||||
@property
|
||||
@@ -384,7 +385,7 @@ class DataBaseProcess(Process):
|
||||
para_list.append([_channel, _data_dict[_channel] + '"***"', _end_time_dict[_channel], _size_dict[_channel], _id_dict[_channel]])
|
||||
with self._psql_conn as conn:
|
||||
with conn.cursor() as sql_cursor:
|
||||
execute_batch(sql_cursor, self._data_raw_recording_sql_str, para_list)
|
||||
execute_batch(sql_cursor, self._new_data_raw_recording_sql_str, para_list)
|
||||
except psycopg2.Error as e:
|
||||
print('recording error', e)
|
||||
return None
|
||||
@@ -549,4 +550,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"."meta_project_info" ('
|
||||
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()
|
||||
|
||||
+83
-544
@@ -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,10 @@ 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.meta_project_info import MetaProjectInfo
|
||||
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
@@ -43,7 +46,7 @@ def _fc(c):
|
||||
return c % len(FORE_COLOR) + FORE_COLOR[0]
|
||||
|
||||
|
||||
class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler):
|
||||
class ControlServer(SocketServer, ControlServerAPI):
|
||||
"""Data Server"""
|
||||
|
||||
def __init__(self, *options):
|
||||
@@ -60,7 +63,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
|
||||
:param options: server options
|
||||
"""
|
||||
super().__init__((ControlAPI, CacheAPI), 'Controller', self.ADDR,
|
||||
super().__init__((ControlAPI), 'Controller', self.ADDR,
|
||||
socket_listen=10,
|
||||
thread_pool_count=16)
|
||||
|
||||
@@ -87,21 +90,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
data_options.repository = device_option.repository
|
||||
self.data_server = DataServerProcess(data_options)
|
||||
|
||||
# experimental protocol
|
||||
# exp_options = ExpManagerOption.get_options(*options)
|
||||
# self.exp_manager = ExpManager(self, exp_options)
|
||||
|
||||
# cache
|
||||
self.cache_manager = CacheManager(self,
|
||||
c.cache_server_cache_size,
|
||||
# time unit from sec to ms
|
||||
c.cache_server_cache_time * 1000)
|
||||
|
||||
# websocket server ###
|
||||
### self.websocket_thread = WebsocketThread(self,
|
||||
### c.websocket_address,
|
||||
### c.websocket_port)
|
||||
|
||||
# remote server / MQTT
|
||||
self.mqtt_thread = None
|
||||
if not c.flag_disable_remote_server:
|
||||
@@ -112,17 +100,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.log_verbose,
|
||||
'MQTT-control-server')
|
||||
|
||||
# routine trash thread
|
||||
self._routine_trash_thread = None
|
||||
# if not c.flag_disable_routine_trash:
|
||||
# self._routine_trash_thread = RoutineTrashThread(self._file_manager,
|
||||
# c.trash_routine_time,
|
||||
# c.trash_expire_time,
|
||||
# c.trash_remove_expire_time)
|
||||
|
||||
# routine data routine
|
||||
self._data_stream_thread = None
|
||||
|
||||
# LED control
|
||||
self.led_thread = LEDControlThread(disable=c.flag_disable_led_control,
|
||||
led_count=c.led_count,
|
||||
@@ -131,6 +108,8 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
# 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.log_verbose)
|
||||
|
||||
if not c.flag_disable_led_control:
|
||||
self.led_thread.set_state(LED.COLOR_RED)
|
||||
|
||||
@@ -141,10 +120,8 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
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
|
||||
|
||||
# temp use variable
|
||||
# self._session = {}
|
||||
# self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
|
||||
|
||||
# indicate those device together
|
||||
self._device_instruction_group = None
|
||||
@@ -155,8 +132,9 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
# _api request build
|
||||
self._api = ApiRequests()
|
||||
|
||||
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread)
|
||||
|
||||
# sqlalchemy
|
||||
Base.metadata.create_all(engine)
|
||||
self._session = Session()
|
||||
|
||||
# init method
|
||||
|
||||
@@ -249,32 +227,16 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
# device manager reset
|
||||
self.submit_thread(self._setup_device)
|
||||
|
||||
# self.submit_thread(self._setup_controller)
|
||||
self._setup_controller()
|
||||
|
||||
# self.run_thread(self._detect_device_thread)
|
||||
|
||||
# experimental protocol manager
|
||||
# if not self._controller_options.flag_disable_exp_manager:
|
||||
# self.exp_manager.setup()
|
||||
# self.exp_manager.reload_protocol()
|
||||
|
||||
# websocket server
|
||||
### self.log_verbose('setup websocket server', pc(self.websocket_thread.websocket_address, YELLOW))
|
||||
# websocket server thread run ###
|
||||
### self.run_thread(self.websocket_thread)
|
||||
|
||||
# broadcast greeting
|
||||
self.broadcast_command(DataMessage.greeting())
|
||||
|
||||
# routine trashing
|
||||
if self._routine_trash_thread is not None:
|
||||
self.run_thread(self._routine_trash_thread)
|
||||
|
||||
# remote server
|
||||
if self.mqtt_thread is not None:
|
||||
self.mqtt_thread.start()
|
||||
# self.run_thread(self.mqtt_thread)
|
||||
|
||||
def _setup_file_manager(self):
|
||||
self.log_verbose('setup file manager')
|
||||
@@ -449,90 +411,14 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.broadcast_command('shutdown')
|
||||
self.data_server.stop_process(external_interrupt)
|
||||
|
||||
self._stop_data_stream_thread()
|
||||
|
||||
self.device_manager.shutdown()
|
||||
|
||||
self.file_manager.shutdown(umount_external=True)
|
||||
|
||||
self.cache_manager.shutdown()
|
||||
|
||||
### self.websocket_thread.close()
|
||||
|
||||
self.led_thread.close()
|
||||
|
||||
if self.mqtt_thread is not None:
|
||||
self.mqtt_thread.shutdown()
|
||||
# self.mqtt_thread.close()
|
||||
|
||||
# user session
|
||||
|
||||
def new_user_session(self) -> str:
|
||||
session = UserSession(None)
|
||||
|
||||
self._session[session.user_session] = session
|
||||
|
||||
self.log_info('new user session', session.user_session)
|
||||
|
||||
return session.user_session
|
||||
|
||||
@logging_info
|
||||
def del_user_session(self, user_session: Optional[str] = None):
|
||||
if user_session is None:
|
||||
self._session.clear()
|
||||
|
||||
else:
|
||||
try:
|
||||
del self._session[user_session]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def get_user_session(self,
|
||||
user_session: Optional[str],
|
||||
new_session = False,
|
||||
allow_empty = False) -> Optional[UserSession]:
|
||||
"""
|
||||
|
||||
:param user_session: user session ID
|
||||
:param new_session: new a user session if *user_session* not found.
|
||||
:param allow_empty: consider empty *user_session* None
|
||||
:return: user session
|
||||
"""
|
||||
|
||||
if user_session is None:
|
||||
session = None
|
||||
|
||||
elif len(user_session) == 0:
|
||||
if allow_empty:
|
||||
session = None
|
||||
else:
|
||||
raise None
|
||||
|
||||
else:
|
||||
session = self._session.get(user_session, None)
|
||||
|
||||
if session is not None:
|
||||
session.time()
|
||||
|
||||
elif new_session:
|
||||
session = UserSession(user_session)
|
||||
|
||||
self._session[session.user_session] = session
|
||||
|
||||
self.log_info('new user session', session.user_session)
|
||||
|
||||
return session
|
||||
|
||||
def expire_user_session(self):
|
||||
current_time = time()
|
||||
|
||||
for user_session in list(self._session.keys()):
|
||||
session = self._session[user_session]
|
||||
|
||||
if session.time(update=False) - current_time > self._user_session_expire:
|
||||
del self._session[user_session]
|
||||
|
||||
# general post action
|
||||
|
||||
def _post_device_list(self) -> List[CompletedDevice]:
|
||||
"""general post action for getting list of connected devices.
|
||||
@@ -869,12 +755,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
def get_device_info(self, device: int) -> Optional[CompletedDevice]:
|
||||
return super().get_device_info(device)
|
||||
|
||||
# @logging_info
|
||||
# def device_call(self, device: int) -> bool:
|
||||
# self.device_manager.call_device(device)
|
||||
#
|
||||
# return True
|
||||
|
||||
@logging_info
|
||||
def device_instruction_all(self, device: int) -> List[str]:
|
||||
return self.device_manager.list_device_instruction(device)
|
||||
@@ -946,12 +826,21 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
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]:
|
||||
@@ -1048,8 +937,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
|
||||
@logging_info
|
||||
def device_parameter(self, device: int, parameter: str, content: Optional[str] = None) -> Any:
|
||||
# if content is not None:
|
||||
# self.broadcast_command('parameter:' + str(device) + '/' + parameter + '/' + content)
|
||||
return self.device_manager.handle_device_parameter_command(device, parameter, content)
|
||||
|
||||
@logging_info
|
||||
@@ -1141,255 +1028,44 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
def device_history_delete(self, user: str, device: Optional[int]) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
# server provide method implement : file manager functions
|
||||
|
||||
@logging_info
|
||||
def file_clean_storage(self) -> bool:
|
||||
return super().file_clean_storage()
|
||||
|
||||
@logging_info
|
||||
def file_index(self) -> RootInfo:
|
||||
return super().file_index()
|
||||
|
||||
@logging_info
|
||||
def file_list(self, path: str) -> DirectoryInfo:
|
||||
return super().file_list(path)
|
||||
|
||||
@logging_info
|
||||
def file_list_range(self, path: str, start: int, end: int) -> DirectoryInfo:
|
||||
return super().file_list_range(path, start, end)
|
||||
|
||||
@logging_info
|
||||
def file_rename(self, path: str, content: str) -> FileInfo:
|
||||
return super().file_rename(path, content)
|
||||
|
||||
@logging_info
|
||||
def file_mkdir(self, path: str) -> DirectoryInfo:
|
||||
return super().file_mkdir(path)
|
||||
|
||||
@logging_info
|
||||
def file_delete(self, path: str) -> bool:
|
||||
return super().file_delete(path)
|
||||
|
||||
@logging_info
|
||||
def file_info(self, path: str) -> FileInfo:
|
||||
return super().file_info(path)
|
||||
|
||||
@logging_info
|
||||
def file_meta_info(self, path: str) -> RecordingMetaFile:
|
||||
return super().file_meta_info(path)
|
||||
|
||||
@logging_info
|
||||
def file_export_info(self, path: str) -> Dict[str, Optional[Path]]:
|
||||
return super().file_export_info(path)
|
||||
|
||||
@logging_info
|
||||
def file_export_functions(self) -> Tuple[ExternalExportFunction, ...]:
|
||||
return super().file_export_functions()
|
||||
|
||||
@logging_info
|
||||
def file_export_parameters(self, ftype: str) -> Tuple[ExternalParameter, ...]:
|
||||
return super().file_export_parameters(ftype)
|
||||
|
||||
@logging_info
|
||||
def file_export(self, ftype: str, path: str, **options: str) -> str:
|
||||
return super().file_export(ftype, path, **options)
|
||||
|
||||
@logging_info
|
||||
def file_segment(self, method: str, path: str) -> Union[None, bool, FileSegment]:
|
||||
return super().file_segment(method, path)
|
||||
|
||||
@logging_info
|
||||
def file_segment_get(self, segment: int, path: str):
|
||||
return super().file_segment_get(segment, path)
|
||||
|
||||
@logging_info
|
||||
def file_handle_open(self, content: str) -> Optional[FileHandle]:
|
||||
info = self.file_manager.info(content)
|
||||
meta = info.meta_file
|
||||
|
||||
if meta is None:
|
||||
raise RuntimeError('not a meta file')
|
||||
|
||||
handle = self.cache_manager.file_open(meta)
|
||||
|
||||
return self.file_handle_info(handle)
|
||||
|
||||
@logging_info
|
||||
def file_handle_info(self, handle: int) -> Optional[FileHandle]:
|
||||
info = self.cache_manager.file_info(handle)
|
||||
|
||||
if info is None:
|
||||
return None
|
||||
|
||||
# modify file path
|
||||
info.shadow_path(self.file_manager.shadow_path(Path(info.filepath)))
|
||||
|
||||
return info
|
||||
|
||||
@logging_info
|
||||
def file_handle_close(self, handle: int):
|
||||
self.cache_manager.file_close(handle)
|
||||
|
||||
@logging_info
|
||||
def user_all(self) -> List[str]:
|
||||
raise super().user_all()
|
||||
|
||||
@logging_info
|
||||
def user_info(self, user: str, *, user_session: Optional[str] = None) -> Optional[AbstractUserSetting]:
|
||||
return super().user_info(user, user_session=user_session)
|
||||
|
||||
@logging_info
|
||||
def user_login(self, user: str, content: str, *,
|
||||
user_session = None) -> ComplexResponse[AbstractUserSetting]:
|
||||
raise super().user_login(user, content, user_session=user_session)
|
||||
|
||||
@logging_info
|
||||
def user_logout(self, user_session: Optional[str] = None) -> None:
|
||||
super().user_logout(user_session)
|
||||
|
||||
@logging_info
|
||||
def user_add(self, user: str, content: str, *,
|
||||
user_session = None) -> ComplexResponse[AbstractUserSetting]:
|
||||
return super().user_add(user, content, user_session=user_session)
|
||||
|
||||
@logging_info
|
||||
def user_del(self, user: str, content: str) -> bool:
|
||||
return super().user_del(user, content)
|
||||
|
||||
@logging_info
|
||||
def user_sync(self, user_session: Optional[str]) -> bool:
|
||||
return super().user_sync(user_session)
|
||||
|
||||
@logging_info
|
||||
def user_configuration_list(self, user_session: Optional[str], **options: str) -> List[str]:
|
||||
return super().user_configuration_list(user_session, **options)
|
||||
|
||||
@logging_info
|
||||
def user_configuration_get(self, name: str, user_session: Optional[str] = None) -> Optional[RecordingMetaFile]:
|
||||
return super().user_configuration_get(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_configuration_add(self, name: str, content: str, user_session: Optional[str] = None) -> bool:
|
||||
return super().user_configuration_add(name, content, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_configuration_del(self, name: str, user_session: Optional[str] = None) -> bool:
|
||||
return super().user_configuration_del(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_configuration_clone(self, name: str, content: str, user_session: Optional[str] = None) -> bool:
|
||||
return super().user_configuration_clone(name, content, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_setup_list(self, user_session: Optional[str] = None) -> List[str]:
|
||||
return super().user_setup_list(user_session)
|
||||
|
||||
@logging_info
|
||||
def user_setup_info(self, name: str, user_session: Optional[str] = None) -> Optional[UserSetup]:
|
||||
return super().user_setup_info(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_setup_new(self, name: str, user_session: Optional[str] = None) -> Optional[UserSetup]:
|
||||
return super().user_setup_new(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_setup_del(self, name: str, user_session: Optional[str] = None) -> bool:
|
||||
return super().user_setup_del(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_alias_list(self, user_session: Optional[str] = None) -> List[UserDeviceAlias]:
|
||||
return super().user_alias_list(user_session)
|
||||
|
||||
@logging_info
|
||||
def user_alias_info(self, name: str, user_session: Optional[str] = None) -> Optional[UserDeviceAlias]:
|
||||
return super().user_alias_info(name, user_session)
|
||||
|
||||
@logging_info
|
||||
def user_alias_edit(self, name: str, content: str, user_session: Optional[str] = None) -> Optional[UserDeviceAlias]:
|
||||
return super().user_alias_edit(name, content, user_session)
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_list(self) -> List[ExpProtocolInfo]:
|
||||
# return self.exp_manager.list_available_protocol()
|
||||
|
||||
@logging_info
|
||||
def exp_pro_create(self, content: str, *,
|
||||
user_session = None) -> int:
|
||||
user_name = self._session_user_name(user_session)
|
||||
|
||||
if user_name is None:
|
||||
raise RuntimeError('require user login')
|
||||
|
||||
self.file_manager.user_setting.user_info(user_name)
|
||||
|
||||
# p = self.exp_manager.create_protocol(content, user_name)
|
||||
return
|
||||
|
||||
@logging_info
|
||||
def run_project(self, project) -> bool:
|
||||
project = self._project_manager.create(project)
|
||||
self._project_manager.run(project)
|
||||
return False
|
||||
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()
|
||||
|
||||
@logging_info
|
||||
def stop_project(self, project) -> bool:
|
||||
if project is not None:
|
||||
self._project_manager.stop_project(project)
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def set_project(self, project, content) -> bool:
|
||||
if project is not None:
|
||||
self._project_manager.set_project(project, content)
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def set_project_cycle(self, project, index, content) -> bool:
|
||||
if project is not None:
|
||||
self._project_manager.set_project_cycle(project, index, content)
|
||||
return True
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_options(self, protocol: int) -> List[ExpOption]:
|
||||
# return self.exp_manager.protocol_options(protocol)
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_option(self, protocol: int, option: str, content: Optional[str] = None) -> bool:
|
||||
# if content == '':
|
||||
# # option reset
|
||||
# if option == '':
|
||||
# # reset all options
|
||||
# self.exp_manager.protocol_reset(protocol)
|
||||
# else:
|
||||
# self.exp_manager.protocol_reset(protocol, *option.split(','))
|
||||
# else:
|
||||
# # option get/set
|
||||
# self.exp_manager.protocol_option(protocol, option, content)
|
||||
|
||||
# return True
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_status_all(self) -> List[AbstractExpProtocolState]:
|
||||
# ret = []
|
||||
|
||||
# for p in self.exp_manager.list_protocol():
|
||||
# s = self.exp_manager.protocol_status(p)
|
||||
|
||||
# if s is not None:
|
||||
# ret.append(s)
|
||||
# else:
|
||||
# ret.append(AbstractExpProtocolState(p))
|
||||
|
||||
# return ret
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_status(self, protocol: int) -> Optional[ExpProtocolState]:
|
||||
# return self.exp_manager.protocol_status(protocol)
|
||||
|
||||
# @logging_info
|
||||
# def exp_pro_command(self, protocol: int, content: str) -> bool:
|
||||
# if content == 'ensure':
|
||||
# return self.exp_manager.ensure_protocol(protocol)
|
||||
|
||||
# elif content == 'start':
|
||||
# self.exp_manager.submit_protocol(protocol)
|
||||
|
||||
# elif content == 'interrupt':
|
||||
# self.exp_manager.interrupt_protocol(protocol)
|
||||
|
||||
# elif content == 'suspend':
|
||||
# self.exp_manager.suspend_protocol(protocol)
|
||||
|
||||
# elif content == 'resume':
|
||||
# self.exp_manager.resume_protocol(protocol)
|
||||
|
||||
# else:
|
||||
# raise RuntimeError('unknown protocol command : ' + content)
|
||||
|
||||
# return True
|
||||
@logging_info
|
||||
def get_running_project(self) -> bool:
|
||||
return self._project_manager.get()
|
||||
|
||||
@logging_info
|
||||
def device_internal_command(self, device: int, oper: str, value: Any) -> bool:
|
||||
@@ -1406,8 +1082,10 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
return True
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE:
|
||||
if device is not None:
|
||||
self._device_set_disable_cache(device, value)
|
||||
return True
|
||||
|
||||
elif oper == InternalInstruction.PREDEFINED_IDLE:
|
||||
device.status = 1
|
||||
return True
|
||||
|
||||
else:
|
||||
@@ -1423,6 +1101,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.log_verbose('update data format', value)
|
||||
|
||||
client = self.data_server.client()
|
||||
project = None
|
||||
if client is not None:
|
||||
info = self.file_manager.use(device)
|
||||
|
||||
@@ -1433,9 +1112,12 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
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 = json.dumps(self.project_manager.get(device.occupied_by_project).info_pass_data_server())
|
||||
|
||||
with client:
|
||||
client.update_device_configuration(device, info.meta_file, value)
|
||||
client.update_device_configuration(device, info.meta_file, value, project)
|
||||
|
||||
def _device_set_disable_cache(self, device: CompletedDevice, disable):
|
||||
if disable:
|
||||
@@ -1459,10 +1141,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
|
||||
def _device_set_sync(self, device: CompletedDevice, sync: bool):
|
||||
if sync:
|
||||
self.log_verbose('start sync', device.device_id)
|
||||
|
||||
self.cache_manager.drop_data(device)
|
||||
|
||||
client = self.data_server.client()
|
||||
if client is not None:
|
||||
info = self.file_manager.use(device)
|
||||
@@ -1473,22 +1151,13 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
filename = format_filename(self.TEMP_FILENAME_EXPR, device)
|
||||
info = self.file_manager.save(device, filename)
|
||||
client.update_device_configuration(device, info.meta_file, RawDataDecoder())
|
||||
print('***456')
|
||||
|
||||
if self._device_instruction_group is None:
|
||||
client.start_sync(device)
|
||||
|
||||
if self._device_instruction_group is None:
|
||||
# broadcast
|
||||
self.broadcast_command(DataMessage.start(device.device_id))
|
||||
|
||||
|
||||
device.status = 1
|
||||
else:
|
||||
self.log_verbose('stop sync', device.device_id)
|
||||
|
||||
if self._device_instruction_group is None:
|
||||
|
||||
start_sync = False
|
||||
|
||||
client = self.data_server.client()
|
||||
if client is not None:
|
||||
with client:
|
||||
@@ -1501,12 +1170,10 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
if start_sync:
|
||||
# unset file info, but keep file path cache
|
||||
self.file_manager.unset(device.device_id)
|
||||
device.status = 0
|
||||
|
||||
# broadcast
|
||||
self.broadcast_command(DataMessage.stop(device.device_id))
|
||||
|
||||
# server provide method implement : websocket broadcast functions
|
||||
|
||||
@logging_info
|
||||
def broadcast_command(self, command: str, device: Optional[int] = None):
|
||||
self.log_verbose(pc('broadcast_command', GREEN),
|
||||
@@ -1516,96 +1183,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
if self.mqtt_thread is not None:
|
||||
self.mqtt_thread.broadcast_command(command, device=device)
|
||||
|
||||
# data stream thread
|
||||
|
||||
def data_request_stream(self, start: bool, handler: DataMessageHandler):
|
||||
if start:
|
||||
t = self._start_data_stream_thread()
|
||||
t.add_handle(handler)
|
||||
|
||||
else:
|
||||
t = self._data_stream_thread
|
||||
|
||||
if t is not None:
|
||||
t.del_handle(handler)
|
||||
|
||||
if not t.has_handle():
|
||||
self._stop_data_stream_thread()
|
||||
|
||||
def _start_data_stream_thread(self) -> DataStreamThread:
|
||||
t = self._data_stream_thread
|
||||
|
||||
if self._data_stream_thread is None:
|
||||
self._data_stream_thread = t = self.run_thread(DataStreamThread(self))
|
||||
|
||||
return t
|
||||
|
||||
def _stop_data_stream_thread(self):
|
||||
t = self._data_stream_thread
|
||||
self._data_stream_thread = None
|
||||
|
||||
if t is not None:
|
||||
t.close()
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
@logging_info
|
||||
def websocket_command(self, command: str) -> Union[None, str, bytes, List[str]]:
|
||||
if command == DataMessage.GREETING:
|
||||
return DataMessage.greeting()
|
||||
|
||||
elif command == DataMessage.SYNC:
|
||||
return self._websocket_command_sync(map(lambda d: d.device_id, self._post_device_list()))
|
||||
|
||||
elif command.startswith(DataMessage.SYNC):
|
||||
_, device_list = part_suffix(command, ':')
|
||||
|
||||
if ',' in device_list:
|
||||
return self._websocket_command_sync(map(int, device_list.split(',')))
|
||||
|
||||
else:
|
||||
return self._websocket_command_sync([int(device_list)])
|
||||
|
||||
elif command.startswith(DataMessage.BROADCAST):
|
||||
_, message = part_suffix(command, ':')
|
||||
|
||||
if message is not None:
|
||||
self.broadcast_command(DataMessage.broadcast(message))
|
||||
|
||||
return None
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def _websocket_command_sync(self, device_list: Iterable[int]) -> Union[str, List[str]]:
|
||||
client = self.data_server.client()
|
||||
|
||||
if client is None:
|
||||
return DataMessage.sync(False)
|
||||
|
||||
else:
|
||||
result_start = []
|
||||
result_stop = []
|
||||
|
||||
with client:
|
||||
for device in device_list:
|
||||
if client.is_sync(device):
|
||||
result_start.append(device)
|
||||
else:
|
||||
result_stop.append(device)
|
||||
|
||||
return [DataMessage.start(result_start), DataMessage.stop(result_stop)]
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def websocket_data_request(self, handler: DataMessageHandler, command: Optional[str]):
|
||||
try:
|
||||
self._handle_command_response(handler, command)
|
||||
|
||||
except (ValueError, IndexError) as e:
|
||||
self.log_warn(e)
|
||||
handler.on_error(DataMessage.warn(str(e)))
|
||||
|
||||
except BaseException as e:
|
||||
self.log_warn(e)
|
||||
handler.on_error(DataMessage.error(str(e)))
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def _handle_command_response(self, handler: DataMessageHandler, command: Optional[str]):
|
||||
"""
|
||||
@@ -1627,29 +1204,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
else:
|
||||
self.cache_manager.get_data_message(handler, response)
|
||||
|
||||
# server provide method implement : cache API
|
||||
|
||||
@logging_verbose
|
||||
def clear(self):
|
||||
self.cache_manager.clear()
|
||||
|
||||
def push_data(self, data: Union[bytes, List[bytes]]):
|
||||
self.cache_manager.push_data(data)
|
||||
|
||||
@logging_verbose
|
||||
def drop_data(self, *device: int):
|
||||
self.cache_manager.drop_data(*device)
|
||||
|
||||
def stop_data(self, device: int):
|
||||
self.cache_manager.stop_data(device)
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
@logging_verbose
|
||||
def notify_data(self, device: int, message: str):
|
||||
self.broadcast_command(message, device=device)
|
||||
|
||||
# led function
|
||||
|
||||
def get_led_state(self) -> str:
|
||||
return self.led_thread.state
|
||||
|
||||
@@ -1657,7 +1212,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.led_thread.set_state(state)
|
||||
|
||||
# hardware send test
|
||||
|
||||
if not _RUNTIME_COMPILE:
|
||||
|
||||
def _hardware_send_test(self, options: Dict[str, str]):
|
||||
@@ -1700,30 +1254,9 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
'export_root': str(self.file_manager.export_root)
|
||||
}
|
||||
|
||||
if section is None or 'cache' in section:
|
||||
ret['cache'] = {
|
||||
'cache_size': self.cache_manager.cache_size,
|
||||
'cache_time': self.cache_manager.cache_time,
|
||||
}
|
||||
|
||||
# if section is None or 'websocket' in section:
|
||||
# ret['websocket'] = {
|
||||
# 'address': self.websocket_thread.websocket_address,
|
||||
# 'port': self.websocket_thread.websocket_port,
|
||||
# }
|
||||
|
||||
if section is None or 'mqtt' in section:
|
||||
ret['mqtt'] = None if self.mqtt_thread is None else self.mqtt_thread.hardware_test()
|
||||
|
||||
if section is None or 'trash' in section:
|
||||
trash_manager = self._routine_trash_thread
|
||||
|
||||
ret['trash'] = None if trash_manager is None else {
|
||||
'routine_interval': trash_manager.routine_interval,
|
||||
'trash_expire': trash_manager.trash_expire,
|
||||
'remove_expire': trash_manager.remove_expire,
|
||||
}
|
||||
|
||||
if section is None or 'led' in section:
|
||||
ret['led'] = {
|
||||
'state_all': list(LED.COLOR.keys()),
|
||||
@@ -1851,7 +1384,13 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
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):
|
||||
|
||||
@@ -41,10 +41,12 @@ class RecordingProcess(Process):
|
||||
connect to DB and send sql command
|
||||
"""
|
||||
|
||||
def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, meta_path,
|
||||
def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, queue_msg, meta_path,
|
||||
device_info, parameter, parent, recording_file_name, data_format,
|
||||
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)
|
||||
|
||||
@@ -82,6 +85,7 @@ class RecordingProcess(Process):
|
||||
|
||||
self._queue_rec = queue_rec
|
||||
self._queue_ds = queue_ds
|
||||
self._queue_msg = queue_msg
|
||||
self.queue_flag = True
|
||||
|
||||
self._is_close = True
|
||||
@@ -104,6 +108,9 @@ class RecordingProcess(Process):
|
||||
self._mem_tailer_len = 6
|
||||
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
||||
|
||||
self._decoder = self.data_format()
|
||||
self._start_time = time()
|
||||
|
||||
def ensure_data_format(self) -> DataDecodeFormat:
|
||||
if isinstance(self._data_format, (str, bytes)):
|
||||
self._data_format = DataDecodeFormat.parse(self._data_format)
|
||||
@@ -132,9 +139,9 @@ class RecordingProcess(Process):
|
||||
decoder._prev_data = self._prev_data
|
||||
decoder._prev_delta_time = self._prev_delta_time
|
||||
decoder._prev_time_stamp = self._prev_time_stamp
|
||||
# elif isinstance(decoder, I4V4Z4T4DataDecoder):
|
||||
elif isinstance(decoder, I4V4Z4T4DataDecoder):
|
||||
# get cycle_time from meta file
|
||||
# decoder._mode = self._meta_file.configuration.MODE
|
||||
decoder._mode = self._meta_file.configuration.get_parameter('MODE')
|
||||
# decoder._cycle_start_time = self._cycle_start_time
|
||||
elif isinstance(decoder, NeuliveThreeOneDataDecoder):
|
||||
# get amp_gain from meta file
|
||||
@@ -150,11 +157,8 @@ class RecordingProcess(Process):
|
||||
decoder._prev_time_stamp = self._prev_time_stamp
|
||||
elif isinstance(decoder, EISZeroOneDataDecoder):
|
||||
# get amp_gain from meta file
|
||||
|
||||
decoder._ac_amp = self._meta_file.configuration.get_parameter('AC_AMP')
|
||||
decoder._mode = self._meta_file.configuration.get_parameter('MODE')
|
||||
decoder._freq_start = self._meta_file.configuration.get_parameter('FREQ_START')
|
||||
decoder._freq_stop = self._meta_file.configuration.get_parameter('FREQ_STOP')
|
||||
decoder._ac_amp = self._meta_file.configuration.get_parameter('EIS_AC_AMP')
|
||||
|
||||
return decoder
|
||||
|
||||
@@ -182,6 +186,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)
|
||||
@@ -199,14 +205,13 @@ class RecordingProcess(Process):
|
||||
self._isTimeOut = True
|
||||
self._timer = current_time
|
||||
|
||||
decoder = self.data_format()
|
||||
# print('sync_data')
|
||||
# print('data',data)
|
||||
|
||||
# print('server/data', self._prev_delta_time,self._prev_time_stamp, self._prev_data)
|
||||
|
||||
if data is None or len(data) == 0:
|
||||
result = decoder.decode(b'')
|
||||
result = self._decoder.decode(b'')
|
||||
if result is not None:
|
||||
ret = result
|
||||
|
||||
@@ -220,25 +225,13 @@ class RecordingProcess(Process):
|
||||
for offset, section in self._foreach_data_section(data):
|
||||
# for section in self._neu_foreach_data_section(data):
|
||||
|
||||
result = decoder.decode(section)
|
||||
result = self._decoder.decode(section)
|
||||
# if self._isTimeOut:
|
||||
# try:
|
||||
# print('result: ', result.data_size)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
try:
|
||||
if isinstance(decoder, I4V4Z4T4DataDecoder) or isinstance(decoder, EISZeroOneDataDecoder):
|
||||
if decoder.isFinishMode is not None and decoder.isFinishMode() == 1:
|
||||
content = {}
|
||||
content['header'] = 'device_instruction/0'
|
||||
content['device'] = result.device
|
||||
content['instruction'] = 'interrupt'
|
||||
self._mqtt_thread.publish('device_instruction',json_stringify(content), True)
|
||||
# self.server.stop_sync(self.device)
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
|
||||
if result is not None:
|
||||
##
|
||||
if len(self._mqtt_send_data_ch_level) == 0:
|
||||
@@ -255,9 +248,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
|
||||
@@ -295,8 +306,8 @@ class RecordingProcess(Process):
|
||||
self._last_cnt[7] = head_counter - 1
|
||||
last_data_cnt = self._last_cnt[7]
|
||||
|
||||
# dont save to section when head or id is wrong
|
||||
if (head != 255 or device_id != device):
|
||||
# dont save to section when head or id is wrong
|
||||
if (head != 255 or device_id != device or head_counter > 255 or head_counter < 0):
|
||||
save = False
|
||||
last_data_cnt = last_data_cnt + 1
|
||||
|
||||
@@ -347,13 +358,14 @@ class RecordingProcess(Process):
|
||||
|
||||
if colum_total == 1:
|
||||
print('this ram data < 3 records, colum_total = ', colum_total)
|
||||
print('raw_data[0]', raw_data[0])
|
||||
return save
|
||||
print('raw_data[0]', list(raw_data[0]))
|
||||
save = True
|
||||
# return save
|
||||
|
||||
elif colum_total == 2:
|
||||
print('this ram data < 3 records, colum_total = ', colum_total)
|
||||
print('raw_data[0]', raw_data[0])
|
||||
print('raw_data[1]', raw_data[1])
|
||||
print('raw_data[0]', list(raw_data[0]))
|
||||
print('raw_data[1]', list(raw_data[1]))
|
||||
if (raw_data[col + 1][1] - raw_data[col][1] == 1) or (raw_data[col][1] == 255 and raw_data[col + 1][1] == 0):
|
||||
save = True
|
||||
|
||||
@@ -597,7 +609,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:
|
||||
|
||||
+277
-115
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "EliteZM15",
|
||||
"name": "Elite_BAT_1.0",
|
||||
"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,
|
||||
"VOLT_MAX": 65536,
|
||||
"Const_Current_Range": 1500001,
|
||||
"BLE_WRITE_MAX": 255
|
||||
@@ -17,7 +18,7 @@
|
||||
"DPV_e_init": {
|
||||
"description": "DPV initial voltage ",
|
||||
"record_meta": true,
|
||||
"initial":20000,
|
||||
"initial": 20000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -28,7 +29,7 @@
|
||||
"DPV_e_final": {
|
||||
"description": "DPV final voltage",
|
||||
"record_meta": true,
|
||||
"initial":30000,
|
||||
"initial": 30000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -39,7 +40,7 @@
|
||||
"DPV_e_1": {
|
||||
"description": "DPV voltage return 1",
|
||||
"record_meta": true,
|
||||
"initial":35000,
|
||||
"initial": 35000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -50,7 +51,7 @@
|
||||
"DPV_e_2": {
|
||||
"description": "DPV voltage return 2",
|
||||
"record_meta": true,
|
||||
"initial":15000,
|
||||
"initial": 15000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -61,7 +62,7 @@
|
||||
"DPV_amp": {
|
||||
"description": "DPV pulse amplitude",
|
||||
"record_meta": true,
|
||||
"initial":25125,
|
||||
"initial": 25125,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -72,7 +73,7 @@
|
||||
"DPV_pul_width": {
|
||||
"description": "DPV pulse width",
|
||||
"record_meta": true,
|
||||
"initial":50,
|
||||
"initial": 50,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -83,7 +84,7 @@
|
||||
"DPV_increment": {
|
||||
"description": "DPV increment",
|
||||
"record_meta": true,
|
||||
"initial":25025,
|
||||
"initial": 25025,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -94,7 +95,7 @@
|
||||
"DPV_step_time": {
|
||||
"description": "DPV step time = time of one period",
|
||||
"record_meta": true,
|
||||
"initial":500,
|
||||
"initial": 500,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -105,7 +106,7 @@
|
||||
"DPV_notify_rate": {
|
||||
"description": "DPV sample rate",
|
||||
"record_meta": true,
|
||||
"initial":1000,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1001
|
||||
],
|
||||
@@ -113,10 +114,24 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"DPV_curr_rec": {
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
25,
|
||||
100
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
101
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"DPV_curr_rec_min": {
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
"initial":25,
|
||||
"initial": 25,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
@@ -127,7 +142,7 @@
|
||||
"DPV_curr_rec_max": {
|
||||
"description": "DPV current recording period end",
|
||||
"record_meta": true,
|
||||
"initial":100,
|
||||
"initial": 100,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
@@ -138,11 +153,8 @@
|
||||
"DPV_pulse_option": {
|
||||
"description": "Invert of pulse option",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
"domain": "bool",
|
||||
"initial": false
|
||||
},
|
||||
"DPV_mode": {
|
||||
"description": "AUTO: 0 / ADVANCED: 1/ ENGINEERING: 2",
|
||||
@@ -157,16 +169,29 @@
|
||||
"DPV_engineering_enable": {
|
||||
"description": "Engineering mode switch",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
"domain": "bool",
|
||||
"initial": false
|
||||
},
|
||||
"V_initial": {
|
||||
"description": "Pulse Mode Segment Voltage",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
50000,
|
||||
25000,
|
||||
25000,
|
||||
25000
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
50001
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"V_initial_0": {
|
||||
"description": "Pulse Mode Segment Voltage 0",
|
||||
"record_meta": true,
|
||||
"initial":50000,
|
||||
"initial": 50000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -177,7 +202,7 @@
|
||||
"V_initial_1": {
|
||||
"description": "Pulse Mode Segment Voltage 1",
|
||||
"record_meta": true,
|
||||
"initial":25000,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -188,7 +213,7 @@
|
||||
"V_initial_2": {
|
||||
"description": "Pulse Mode Segment Voltage 2",
|
||||
"record_meta": true,
|
||||
"initial":25000,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -199,7 +224,7 @@
|
||||
"V_initial_3": {
|
||||
"description": "Pulse Mode Segment Voltage 3",
|
||||
"record_meta": true,
|
||||
"initial":25000,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
50001
|
||||
],
|
||||
@@ -207,10 +232,26 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"t_pulse": {
|
||||
"description": "Pulse Mode Segment Duration",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
750,
|
||||
9250,
|
||||
1000,
|
||||
1000
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
1000001
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"t_pulse_0": {
|
||||
"description": "Pulse Mode Segment Duration 0",
|
||||
"record_meta": true,
|
||||
"initial":750,
|
||||
"initial": 750,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -221,7 +262,7 @@
|
||||
"t_pulse_1": {
|
||||
"description": "Pulse Mode Segment Duration 1",
|
||||
"record_meta": true,
|
||||
"initial":9250,
|
||||
"initial": 9250,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -232,7 +273,7 @@
|
||||
"t_pulse_2": {
|
||||
"description": "Pulse Mode Segment Duration 2",
|
||||
"record_meta": true,
|
||||
"initial":1000,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -243,7 +284,7 @@
|
||||
"t_pulse_3": {
|
||||
"description": "Pulse Mode Segment Duration 3",
|
||||
"record_meta": true,
|
||||
"initial":1000,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1000001
|
||||
],
|
||||
@@ -251,10 +292,40 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CURR_REC": {
|
||||
"description": "Pulse Mode Current Recording Period",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
[
|
||||
35,
|
||||
90
|
||||
],
|
||||
[
|
||||
35,
|
||||
99
|
||||
],
|
||||
[
|
||||
35,
|
||||
95
|
||||
],
|
||||
[
|
||||
35,
|
||||
95
|
||||
]
|
||||
],
|
||||
"domain": {
|
||||
"list": {
|
||||
"list": [
|
||||
100
|
||||
]
|
||||
}
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"CURR_REC_START_0": {
|
||||
"description": "Pulse Mode Current Recording Period Start",
|
||||
"record_meta": true,
|
||||
"initial":35,
|
||||
"initial": 35,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -265,7 +336,7 @@
|
||||
"CURR_REC_START_1": {
|
||||
"description": "Pulse Mode Current Recording Period Start",
|
||||
"record_meta": true,
|
||||
"initial":35,
|
||||
"initial": 35,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -276,7 +347,7 @@
|
||||
"CURR_REC_START_2": {
|
||||
"description": "Pulse Mode Current Recording Period Start",
|
||||
"record_meta": true,
|
||||
"initial":35,
|
||||
"initial": 35,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -287,7 +358,7 @@
|
||||
"CURR_REC_START_3": {
|
||||
"description": "Pulse Mode Current Recording Period Start",
|
||||
"record_meta": true,
|
||||
"initial":35,
|
||||
"initial": 35,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -298,7 +369,7 @@
|
||||
"CURR_REC_END_0": {
|
||||
"description": "Pulse Mode Current Recording Period End",
|
||||
"record_meta": true,
|
||||
"initial":90,
|
||||
"initial": 90,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -309,7 +380,7 @@
|
||||
"CURR_REC_END_1": {
|
||||
"description": "Pulse Mode Current Recording Period End",
|
||||
"record_meta": true,
|
||||
"initial":99,
|
||||
"initial": 99,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -320,7 +391,7 @@
|
||||
"CURR_REC_END_2": {
|
||||
"description": "Pulse Mode Current Recording Period End",
|
||||
"record_meta": true,
|
||||
"initial":95,
|
||||
"initial": 95,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -331,7 +402,7 @@
|
||||
"CURR_REC_END_3": {
|
||||
"description": "Pulse Mode Current Recording Period End",
|
||||
"record_meta": true,
|
||||
"initial":95,
|
||||
"initial": 95,
|
||||
"domain": [
|
||||
100
|
||||
],
|
||||
@@ -339,6 +410,40 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"segment_ui_order": {
|
||||
"description": "Pulse Mode Segment Order",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
0,
|
||||
1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
-1,
|
||||
6
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"segment_order": {
|
||||
"description": "Pulse Mode Segment Order",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
0,
|
||||
1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
-1,
|
||||
6
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"segment_ui_order_0": {
|
||||
"description": "Pulse Mode Segment UI Order 0, value: segment ID + 1",
|
||||
"record_meta": true,
|
||||
@@ -478,13 +583,14 @@
|
||||
"Constant Current",
|
||||
"Cyclic Voltammetry",
|
||||
"Linear Sweep Voltammetry",
|
||||
"Chronoamperometric Graph",
|
||||
"Chronoamperometric",
|
||||
"Cali DAC - test",
|
||||
"Cali ADC - test",
|
||||
"Dev Mode",
|
||||
"Open Circuit Potential",
|
||||
"Pulse Sensing",
|
||||
"Differential Pulse Voltammetry (DPV)"
|
||||
"Differential Pulse Voltammetry (DPV)",
|
||||
"Chronopotentiometry"
|
||||
]
|
||||
},
|
||||
"VOLT_ORIGIN": {
|
||||
@@ -644,7 +750,7 @@
|
||||
},
|
||||
"CURRNET_LIMIT_VALUE": {
|
||||
"description": "Current value Setting",
|
||||
"initial":1500000,
|
||||
"initial": 1500000,
|
||||
"domain": [
|
||||
"Const_Current_Range"
|
||||
],
|
||||
@@ -685,6 +791,15 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CC_CP_SPEED": {
|
||||
"description": "charge speed for CC and CP mode",
|
||||
"initial": 1,
|
||||
"value": [
|
||||
"low",
|
||||
"normal",
|
||||
"high"
|
||||
]
|
||||
},
|
||||
"ADC_LEVEL_I_15": {
|
||||
"description": "ADC level",
|
||||
"record_meta": true,
|
||||
@@ -762,6 +877,17 @@
|
||||
"s",
|
||||
"ms"
|
||||
]
|
||||
},
|
||||
"TIME_DURATION": {
|
||||
"description": "Run duration",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
"TIME_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
@@ -812,7 +938,8 @@
|
||||
"7": "set_adc_gain_I",
|
||||
"8": "set_adc_gain_I",
|
||||
"9": "set_adc_gain_I",
|
||||
"13": "set_adc_gain_I"
|
||||
"13": "set_adc_gain_I",
|
||||
"16": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -827,7 +954,8 @@
|
||||
"7": "set_adc_gain_Vin",
|
||||
"8": "set_adc_gain_Vin",
|
||||
"9": "set_adc_gain_Vin",
|
||||
"13": "set_adc_gain_Vin"
|
||||
"13": "set_adc_gain_Vin",
|
||||
"16": "set_adc_gain_Vin"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -845,7 +973,8 @@
|
||||
"9": "curve_const_vscan",
|
||||
"13": "curve_ocp",
|
||||
"14": "curve_pulse_sensing",
|
||||
"15": "curve_dpv"
|
||||
"15": "curve_dpv",
|
||||
"16": "curve_cp"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1043,6 +1172,7 @@
|
||||
"vb": "Const_Current_value",
|
||||
"vc": "VOLTSTOP_MAX",
|
||||
"vd": "VOLTSTOP_MIN",
|
||||
"ve": "CC_CP_SPEED",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1054,7 +1184,31 @@
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
"2B>pe"
|
||||
"2B>pe;",
|
||||
"4b>0b0001;4b>ve"
|
||||
]
|
||||
},
|
||||
"curve_cp": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "Charge",
|
||||
"vb": "Const_Current_value",
|
||||
"vc": "VOLTSTOP_MAX",
|
||||
"vd": "VOLTSTOP_MIN",
|
||||
"ve": "CC_CP_SPEED",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X0C;",
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
"2B>pe;",
|
||||
"4b>0b0000;4b>ve"
|
||||
]
|
||||
},
|
||||
"curve_cv3": {
|
||||
@@ -1180,58 +1334,67 @@
|
||||
},
|
||||
"curve_pulse_sensing": [
|
||||
{
|
||||
"expression": "segment_ui_order_0",
|
||||
"expression": "segment_ui_order[0]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_1",
|
||||
"expression": "segment_ui_order[1]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_2",
|
||||
"expression": "segment_ui_order[2]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "segment_ui_order_3",
|
||||
"expression": "segment_ui_order[3]",
|
||||
"when": {
|
||||
"1": "pul_sen_segment_0",
|
||||
"2": "pul_sen_segment_1",
|
||||
"3": "pul_sen_segment_2",
|
||||
"4": "pul_sen_segment_3"
|
||||
"0": "pul_sen_segment_0",
|
||||
"1": "pul_sen_segment_1",
|
||||
"2": "pul_sen_segment_2",
|
||||
"3": "pul_sen_segment_3"
|
||||
}
|
||||
},
|
||||
"pul_sen_start"
|
||||
],
|
||||
"pul_sen_start": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X0D;",
|
||||
"1XFF"
|
||||
"1XFF",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd"
|
||||
]
|
||||
},
|
||||
"pul_sen_segment_0": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_0",
|
||||
"vb": "t_pulse_0",
|
||||
"vc": "CURR_REC_START_0",
|
||||
"vd": "CURR_REC_END_0",
|
||||
"ve": "segment_order_0 - 1",
|
||||
"va": "V_initial[0]",
|
||||
"vb": "t_pulse[0]",
|
||||
"vc": "CURR_REC[0][0]",
|
||||
"vd": "CURR_REC[0][1]",
|
||||
"ve": "segment_order.index(segment_order[0])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1247,11 +1410,11 @@
|
||||
"pul_sen_segment_1": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_1",
|
||||
"vb": "t_pulse_1",
|
||||
"vc": "CURR_REC_START_1",
|
||||
"vd": "CURR_REC_END_1",
|
||||
"ve": "segment_order_1 - 1",
|
||||
"va": "V_initial[1]",
|
||||
"vb": "t_pulse[1]",
|
||||
"vc": "CURR_REC[1][0]",
|
||||
"vd": "CURR_REC[1][1]",
|
||||
"ve": "segment_order.index(segment_order[1])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1267,11 +1430,11 @@
|
||||
"pul_sen_segment_2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_2",
|
||||
"vb": "t_pulse_2",
|
||||
"vc": "CURR_REC_START_2",
|
||||
"vd": "CURR_REC_END_2",
|
||||
"ve": "segment_order_2 - 1",
|
||||
"va": "V_initial[2]",
|
||||
"vb": "t_pulse[2]",
|
||||
"vc": "CURR_REC[2][0]",
|
||||
"vd": "CURR_REC[2][1]",
|
||||
"ve": "segment_order.index(segment_order[2])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1287,11 +1450,11 @@
|
||||
"pul_sen_segment_3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "V_initial_3",
|
||||
"vb": "t_pulse_3",
|
||||
"vc": "CURR_REC_START_3",
|
||||
"vd": "CURR_REC_END_3",
|
||||
"ve": "segment_order_3 - 1",
|
||||
"va": "V_initial[3]",
|
||||
"vb": "t_pulse[3]",
|
||||
"vc": "CURR_REC[3][0]",
|
||||
"vd": "CURR_REC[3][1]",
|
||||
"ve": "segment_order.index(segment_order[3])",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
@@ -1304,9 +1467,7 @@
|
||||
"2B>va;4B>vb;1B>vc;1B>vd;1B>ve"
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
"curve_dpv":[
|
||||
"curve_dpv": [
|
||||
{
|
||||
"expression": "DPV_mode",
|
||||
"when": {
|
||||
@@ -1354,8 +1515,8 @@
|
||||
"parameter": {
|
||||
"va": "DPV_step_time",
|
||||
"vb": "DPV_notify_rate",
|
||||
"vc": "DPV_curr_rec_min",
|
||||
"vd": "DPV_curr_rec_max"
|
||||
"vc": "DPV_curr_rec[0]",
|
||||
"vd": "DPV_curr_rec[1]"
|
||||
},
|
||||
"data": [
|
||||
"1X0E;",
|
||||
@@ -1365,14 +1526,20 @@
|
||||
},
|
||||
"dpv_auto_mode_ins_final": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X0E;",
|
||||
"1XFF"
|
||||
"1XFF;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd"
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
|
||||
"dpv_advanced_mode": [
|
||||
"dpv_advanced_mode_ins_1",
|
||||
"dpv_advanced_mode_ins_2",
|
||||
@@ -1412,8 +1579,8 @@
|
||||
"parameter": {
|
||||
"va": "DPV_step_time",
|
||||
"vb": "DPV_notify_rate",
|
||||
"vc": "DPV_curr_rec_min",
|
||||
"vd": "DPV_curr_rec_max"
|
||||
"vc": "DPV_curr_rec[0]",
|
||||
"vd": "DPV_curr_rec[1]"
|
||||
},
|
||||
"data": [
|
||||
"1X10;",
|
||||
@@ -1437,9 +1604,18 @@
|
||||
},
|
||||
"dpv_advanced_mode_ins_final": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pc": "DAC_LEVEL_V_OUT_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1X10;",
|
||||
"1XFF"
|
||||
"1XFF;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd"
|
||||
]
|
||||
},
|
||||
"dpv_engineering_mode": [
|
||||
@@ -1457,18 +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')"
|
||||
@@ -1499,6 +1663,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+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
@@ -0,0 +1,645 @@
|
||||
{
|
||||
"name": "Elite_EIS_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": 0
|
||||
},
|
||||
"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
|
||||
],
|
||||
"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"
|
||||
]
|
||||
},
|
||||
"GENERAL_HS_RTIA": {
|
||||
"description": "High speed rtia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"on_change": "set_general_hs_rtia"
|
||||
},
|
||||
"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": 25,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"EIS_FREQ": {
|
||||
"description": "[start, stop] of frequency scan",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
"FREQ_MAX"
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"EIS_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"EIS_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"EIS_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"EIS_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"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": 25,
|
||||
"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": {
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"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,651 @@
|
||||
{
|
||||
"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": 4,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"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": 25,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"EIS_FREQ": {
|
||||
"description": "[start, stop] of frequency scan",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
"FREQ_MAX"
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"EIS_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"EIS_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"EIS_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"EIS_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"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": 25,
|
||||
"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,651 @@
|
||||
{
|
||||
"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": 4,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"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": 25,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"EIS_FREQ": {
|
||||
"description": "[start, stop] of frequency scan",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
"list": [
|
||||
"FREQ_MAX"
|
||||
]
|
||||
},
|
||||
"value": "VALUE"
|
||||
},
|
||||
"EIS_PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"EIS_SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"EIS_DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"EIS_AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8
|
||||
]
|
||||
},
|
||||
"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": 25,
|
||||
"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",
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "Elite_TRI",
|
||||
"name": "Elite_TRIG_0.1",
|
||||
"version": "1.2.30",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Trigger.*",
|
||||
@@ -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,433 +0,0 @@
|
||||
{
|
||||
"name": "EliteEIS",
|
||||
"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": 0
|
||||
},
|
||||
"constant": {
|
||||
"FREQ_MAX": 4294967296,
|
||||
"VOLT_MAX": 65536,
|
||||
"BLE_WRITE_MAX": 255
|
||||
},
|
||||
"parameters": {
|
||||
"CHANNEL": {
|
||||
"derzteription": "record channels",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "[0, 1, 2]"
|
||||
},
|
||||
"CHANNEL_LABEL": {
|
||||
"description": "channel label",
|
||||
"record_meta": true,
|
||||
"domain": "property",
|
||||
"value": "['current', 'voltage', 'impedance']"
|
||||
},
|
||||
"SAMPLE_RATE": {
|
||||
"description": "data sampling rate",
|
||||
"record_meta": true,
|
||||
"initial": 1000,
|
||||
"domain": [
|
||||
1001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
},
|
||||
"on_change": "set_sample_rate"
|
||||
},
|
||||
"AMP_GAIN": {
|
||||
"description": "amp gain",
|
||||
"record_meta": true,
|
||||
"domain": "constant",
|
||||
"value": 1
|
||||
},
|
||||
"MODE": {
|
||||
"description": "working mode",
|
||||
"record_meta": true,
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
"FREQ_START": {
|
||||
"description": "Start of Freq Scan",
|
||||
"record_meta": true,
|
||||
"initial": 13422819,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"FREQ_STOP": {
|
||||
"description": "End of Freq Scan",
|
||||
"record_meta": true,
|
||||
"initial": 7,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"DELAY": {
|
||||
"description": "Wait x peroid before start taking measurements",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"domain": [
|
||||
101
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"AVERAGE_NUM": {
|
||||
"description": "Number of sample used for average funciton",
|
||||
"record_meta": true,
|
||||
"initial": 8,
|
||||
"value": [
|
||||
2,
|
||||
4,
|
||||
8,
|
||||
16
|
||||
]
|
||||
},
|
||||
"DC_BIAS": {
|
||||
"description": "DC voltage bias in mV",
|
||||
"record_meta": true,
|
||||
"initial": 15000,
|
||||
"domain": [
|
||||
35001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"AC_AMP": {
|
||||
"description": "AC Amplitude in mV",
|
||||
"record_meta": true,
|
||||
"initial": 25,
|
||||
"domain": [
|
||||
2048
|
||||
]
|
||||
},
|
||||
"SCALE": {
|
||||
"description": "Point spacing pattern",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
},
|
||||
"PPD": {
|
||||
"description": "Point per decades",
|
||||
"record_meta": true,
|
||||
"initial": 10,
|
||||
"domain": [
|
||||
11
|
||||
]
|
||||
},
|
||||
"RTIA": {
|
||||
"description": "High speed tia gain",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
]
|
||||
},
|
||||
"ADC_VALUE_I": {
|
||||
"description": "ADC value current value",
|
||||
"domain": "int"
|
||||
},
|
||||
"Scan_Rate": {
|
||||
"description": "Voltage Scan Rate",
|
||||
"record_meta": true,
|
||||
"initial": 10000,
|
||||
"domain": [
|
||||
100001
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CTRL_HIGH_Z_15": {
|
||||
"description": "ctrl highZ level",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"value": [
|
||||
"On",
|
||||
"Off"
|
||||
],
|
||||
"on_change": "set_ctrl_highZ"
|
||||
},
|
||||
"ADC_LEVEL_I_15": {
|
||||
"description": "ADC level",
|
||||
"record_meta": true,
|
||||
"initial": 4,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"auto"
|
||||
],
|
||||
"on_change": "set_adc_gain_I"
|
||||
},
|
||||
"ADC_LEVEL_V_IN_15": {
|
||||
"description": "ADC level",
|
||||
"record_meta": true,
|
||||
"initial": 3,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"auto"
|
||||
],
|
||||
"on_change": "set_adc_gain_Vin"
|
||||
},
|
||||
"VOLT_INITIAL": {
|
||||
"description": "Initial Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_MAX": {
|
||||
"description": "Max Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_MIN": {
|
||||
"description": "Min Voltage of Scan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"CYCLE_NUMBER": {
|
||||
"description": "CV cycle number",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"domain": [
|
||||
65536
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
"description": "send msg to elite",
|
||||
"domain": {
|
||||
"list": [
|
||||
"BLE_WRITE_MAX"
|
||||
]
|
||||
},
|
||||
"initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
|
||||
"value": "VALUE"
|
||||
},
|
||||
"BLE_READ": {
|
||||
"description": "receive msg from elite",
|
||||
"domain": "int"
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
"start": [
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"*": "start_data"
|
||||
}
|
||||
}
|
||||
],
|
||||
"start_data": [
|
||||
"data_format_cali",
|
||||
"_notify(True)",
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_Vin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis_para2",
|
||||
"1": "curve_cv3_para2"
|
||||
}
|
||||
},
|
||||
"_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_sample_rate": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"XE0;2B>va"
|
||||
]
|
||||
},
|
||||
"set_adc_gain_I": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XE1;X05;B>ADC_LEVEL_I_15"
|
||||
]
|
||||
},
|
||||
"set_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"
|
||||
]
|
||||
},
|
||||
"curve_eis": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "FREQ_START",
|
||||
"fb": "FREQ_STOP",
|
||||
"dp": "DELAY",
|
||||
"dc": "DC_BIAS",
|
||||
"am": "AC_AMP",
|
||||
"an": "AVERAGE_NUM",
|
||||
"rt": "RTIA",
|
||||
"pp": "PPD",
|
||||
"sp": "SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1XD1;1X01;4B>fa;4B>fb;2B>dp"
|
||||
]
|
||||
},
|
||||
"curve_eis_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"fa": "FREQ_START",
|
||||
"fb": "FREQ_STOP",
|
||||
"dp": "DELAY",
|
||||
"dc": "DC_BIAS",
|
||||
"am": "AC_AMP",
|
||||
"an": "AVERAGE_NUM",
|
||||
"rt": "RTIA",
|
||||
"pp": "PPD",
|
||||
"sp": "SCALE"
|
||||
},
|
||||
"data": [
|
||||
"1XD1;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
|
||||
]
|
||||
},
|
||||
"curve_cv3": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_INITIAL",
|
||||
"vb": "VOLT_MAX",
|
||||
"vc": "VOLT_MIN",
|
||||
"ve": "Scan_Rate",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1XD2;1X01;2B>va;2B>vb;2B>vc;"
|
||||
]
|
||||
},
|
||||
"curve_cv3_para2": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_INITIAL",
|
||||
"vb": "VOLT_MAX",
|
||||
"vc": "VOLT_MIN",
|
||||
"ve": "Scan_Rate",
|
||||
"vf": "SAMPLE_RATE",
|
||||
"cn": "CYCLE_NUMBER"
|
||||
},
|
||||
"data": [
|
||||
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"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')"
|
||||
],
|
||||
"ble_write": {
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"XFF;",
|
||||
"1B>BLE_WRITE[0];1B>BLE_WRITE[1];1B>BLE_WRITE[2];1B>BLE_WRITE[3];",
|
||||
"1B>BLE_WRITE[4];1B>BLE_WRITE[5];1B>BLE_WRITE[6];1B>BLE_WRITE[7];",
|
||||
"1B>BLE_WRITE[8];1B>BLE_WRITE[9];1B>BLE_WRITE[10];1B>BLE_WRITE[11];",
|
||||
"1B>BLE_WRITE[12];1B>BLE_WRITE[13];1B>BLE_WRITE[14];1B>BLE_WRITE[15];",
|
||||
"1B>BLE_WRITE[16];"
|
||||
]
|
||||
},
|
||||
"dev_version": [
|
||||
"CIS_VERSION",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
],
|
||||
"dev_battery": [
|
||||
"CIS_VOLT",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,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
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
find /home/pi -maxdepth 1 -type f -iname '*.out' -mtime +30 -delete
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/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
|
||||
|
||||
# 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
|
||||
Reference in New Issue
Block a user