Compare commits

..

1 Commits

Author SHA1 Message Date
peterlu14 c894bf7c6f test data 2022-08-02 14:16:22 +08:00
46 changed files with 1036 additions and 2764 deletions
-1
View File
@@ -7,4 +7,3 @@
/.vscode
/media
python/biopro/sever/_identify.py
*.log
+27 -56
View File
@@ -78,8 +78,6 @@ 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
@@ -96,7 +94,6 @@ git clone https://gitlab.com/wisetop/controller/wisetopdataserver.git
```
cd ~/wisetopdataserver
pip3 install -r requirements.txt
pip3 install SQLAlchemy
```
##### Packages version
```
@@ -158,8 +155,8 @@ reboot
###### Set pi password
```
cd ~
passwd
$cd ~
$passwd
Current password:raspberry
New password:5k6zj454778225
Retype new password:5k6zj454778225
@@ -198,11 +195,11 @@ exit 0
### MQTT broker install
###### 1.Install mosquitto
sudo apt-get install mosquitto mosquitto-clients
$sudo apt-get install mosquitto mosquitto-clients
###### 2.Enable Remote Access
sudo vim /etc/mosquitto/conf.d/default.conf
$sudo vim /etc/mosquitto/conf.d/default.conf
add the code following as:
```
@@ -213,13 +210,13 @@ protocol websockets
allow_anonymous true
```
###### 3.restart mqtt broker
sudo systemctl restart mosquitto
$sudo systemctl restart mosquitto
###### 4.Robust MQTT
create mosquitto_restart.sh
cd ~
sudo vim mosquitto_restart.sh
$cd ~
$sudo vim mosquitto_restart.sh
add the code following as:
@@ -236,16 +233,16 @@ echo "$SERVICE is currently running" >> /home/ubuntu/cron.log
exit 0
```
###### 5.add mosquitto_restart.sh to root routing
sudo chmod +x mosquitto_restart.sh
sudo -i
crontab -e
$sudo chmod +x mosquitto_restart.sh
$sudo -i
$crontab -e
add the code following as:
```
*/5 * * * * /home/pi/mosquitto_restart.sh
```
###### 6.Auto run MQTT broker when when pi-start
sudo vim /etc/rc.local
$sudo vim /etc/rc.local
add the code following as:
```
@@ -254,31 +251,31 @@ sudo nohup systemctl restart mosquitto
### Setting up a Routed Wireless Access Point
###### 1.Install AP and Management Software
sudo apt install hostapd
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo apt install dnsmasq
sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent
$sudo apt install hostapd
$sudo systemctl unmask hostapd
$sudo systemctl enable hostapd
$sudo apt install dnsmasq
$sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent
###### 2.Set up the Network Router
sudo nano /etc/dhcpcd.conf
$sudo nano /etc/dhcpcd.conf
```
interface wlan0
static ip_address=192.168.2.1/24
nohook wpa_supplicant
```
sudo nano /etc/sysctl.d/routed-ap.conf
$sudo nano /etc/sysctl.d/routed-ap.conf
```
# Enable IPv4 routing
net.ipv4.ip_forward=1
```
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo netfilter-persistent save
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
$sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$sudo netfilter-persistent save
$sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo nano /etc/dnsmasq.conf
$sudo nano /etc/dnsmasq.conf
```
interface=wlan0 # Listening interface
@@ -289,10 +286,10 @@ address=/gw.wlan/192.168.2.1
# Alias for this router
```
###### 3.Ensure Wireless Operation
sudo rfkill unblock wlan
$sudo rfkill unblock wlan
###### 4.Configure the AP Software
sudo nano /etc/hostapd/hostapd.conf
$sudo nano /etc/hostapd/hostapd.conf
```
country_code=TW
@@ -317,13 +314,11 @@ wme_enabled=1
ht_capab=[HT40+][SHORT-GI-40]
```
###### 5.Running the new Wireless AP
sudo systemctl reboot
$sudo systemctl reboot
### Install Apache2
sudo apt install apache2
### Deploy web site
sudo vim /etc/apache2/sites-available/000-default.conf
### Set web site
$sudo vim ./sites-available/000-default.conf
```
<VirtualHost *:8080> #80------>8080
# The ServerName directive sets the request scheme, hostname and port that
@@ -363,27 +358,3 @@ sudo vim /etc/apache2/sites-available/000-default.conf
##### raspberry website document:
> https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md
# ChangeLog
[2022.12.28]
change meta_project_info to project_metas
change project_report to project_reports
alter table project_meta column cycle type string to jsonb
[2022.11.16]
add python package SQLAlchemy
add new column project(int4) in postgresSQL table recording_meta_datas
add new postgresSQL table project_report
add new postgresSQL table meta_project_info
[2022.10.18]
socektTimeout from 1s -> 5s
socketListen from 3 -> 20
[2022.09.30]
add new column cycle(jsonb) in postgresSQL table projects
[2022.9.28]
add python package numpy
-9
View File
@@ -1585,15 +1585,6 @@ class ControlAPI(metaclass=Router):
def stop_project(self, project) -> bool:
raise NotImplementedError()
def set_project(self, project, content) -> bool:
raise NotImplementedError()
def set_project_cycle(self, project, index, content) -> bool:
raise NotImplementedError()
def show_device_data(self, device) -> bool:
raise NotImplementedError()
# noinspection PyAbstractClass
class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)):
+3 -16
View File
@@ -87,8 +87,7 @@ 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],
project_info: str):
data_format: Union[AnyStr, DataDecodeFormat]):
"""set device configuration.
:param device: device ID
@@ -131,14 +130,6 @@ 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
@@ -155,8 +146,7 @@ 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],
project_info: str):
data_format: Union[AnyStr, DataDecodeFormat]):
# meta file
if isinstance(meta_file, str):
@@ -188,7 +178,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, project_info)
self.send_command('update_device_configuration', device, meta_file, data_format)
def is_sync(self, device: Union[None, int, Device] = None) -> bool:
if isinstance(device, Device):
@@ -201,9 +191,6 @@ 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, ...]:
-10
View File
@@ -1,10 +0,0 @@
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()
-75
View File
@@ -1,75 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
class Collection(Base):
__tablename__ = "collections"
id = Column(Integer, primary_key=True)
name = Column(String(255))
parent = Column(JSONB)
controller_id = Column(Integer)
type = Column(String(255))
description = Column(String(255))
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_collection(cls, collection_name, parent, duplicate=False):
with Session() as session:
name = cls.check_name_duplicate(collection_name, parent, 0, duplicate=duplicate)
if name == None:
return session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
else:
collection = Collection(
name = name,
parent = parent,
type= "folder",
)
session.add(collection)
session.commit()
session.refresh(collection)
return collection
@classmethod
def check_name_duplicate(cls, collection_name, parent, n, _session = None, duplicate=False):
if _session == None:
with Session() as session:
result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
if result is None:
return cls.generate_name(collection_name, n)
else:
if duplicate == True:
return None
else:
new_num = n + 1
# new_name = f"{collection_name}({new_num})"
return cls.check_name_duplicate(collection_name, parent, new_num, session)
else:
result = _session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
if result is None:
return cls.generate_name(collection_name, n)
else:
new_num = n + 1
# new_name = f"{collection_name}({new_num})"
return cls.check_name_duplicate(collection_name, parent, new_num, _session)
@classmethod
def generate_name(cls, collection_name, n):
if n==0:
return collection_name
else:
return f"{collection_name}({n})"
@classmethod
def find_collection(cls, collection_name, parent):
with Session() as session:
result = session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
return result
-24
View File
@@ -1,24 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base, Session
class RecordingDataMeta(Base):
__tablename__ = "recording_data_metas"
id = Column(Integer, primary_key=True)
path = Column(String(255))
name = Column(String(255))
parent = Column(JSONB)
size = Column(String(255))
time_duration = (String(255))
raw_data = Column(JSONB)
project = 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})"
-24
View File
@@ -1,24 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base
class Project(Base):
__tablename__ = "project"
id = Column(Integer, primary_key=True)
name = Column(String)
desc = Column(String)
task = Column(JSONB)
cycle = Column(JSONB)
device = Column(JSONB)
uuid = Column(String(36))
user_auth = Column(JSONB)
deleted = Column(Boolean, default = False)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
# def __repr__(self):
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
-29
View File
@@ -1,29 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base, Session
class MetaProjectInfo(Base):
__tablename__ = "project_metas"
id = Column(Integer, primary_key=True)
project = Column(String(36))
cycle = Column(JSONB)
task = Column(JSONB)
serial_number = Column(Integer)
deleted = Column(Boolean, default = False)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_project_meta(cls, project):
with Session() as session:
project_meta = MetaProjectInfo(project = project['project'], cycle= project['cycle'], task=project['task'], serial_number=int(project['serial_number']))
session.add(project_meta)
session.commit()
return project_meta.id
# def __repr__(self):
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
-24
View File
@@ -1,24 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base
class ProjectReport(Base):
__tablename__ = "project_reports"
id = Column(Integer, primary_key=True)
name = Column(String)
desc = Column(String)
task = Column(JSONB)
cycle = Column(JSONB)
device = Column(JSONB)
uuid = Column(String(36))
user_auth = Column(JSONB)
deleted = Column(Boolean, default = False)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
# def __repr__(self):
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
-88
View File
@@ -1,88 +0,0 @@
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, Text
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
# build a model class with a specific table name
def get_raw_model(channel):
tablename = str(channel) + '_recording_data_raws' # dynamic table name
class_name = 'RECORDING_DATA_RAWS' # dynamic class name
print('get_raw_model', tablename)
for mapper in Base.registry.mappers:
cls = mapper.class_
classname = cls.__name__
tblname = cls.__tablename__
print(cls, classname, tblname)
if (classname == class_name):
if tblname == tablename:
return cls
Model = type(class_name, (RECORDING_DATA_RAWS,), {
'__tablename__': tablename
})
return Model
class RECORDING_DATA_RAWS(Base):
__abstract__ = True
id = Column(Integer, primary_key=True)
name = Column(String(255))
parent = Column(Integer)
size = Column(String(255))
path = Column(JSONB)
uuid = Column(String(255))
serial_number = Column(String(255))
data_format = Column(String(255))
channel = Column(Integer)
start_time = Column(String(255))
end_time = Column(String(255))
data = Column(Text)
compressed = Column(Boolean)
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
# @classmethod
# def create_subject_data(cls, subject_id, project, meta, data):
# with Session() as session:
# subject = Subject(
# subject_id = subject_id,
# project = project,
# meta= meta,
# data = data
# )
# session.add(subject)
# session.commit()
# return subject
# @classmethod
# def check_name_duplicate(cls, collection_name, parent, n):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
# if result is None:
# return cls.generate_name(collection_name, n)
# else:
# new_num = n + 1
# # new_name = f"{collection_name}({new_num})"
# return cls.check_name_duplicate(collection_name, parent, new_num)
# @classmethod
# def generate_name(cls, collection_name, n):
# if n==0:
# return collection_name
# else:
# return f"{collection_name}({n})"
# @classmethod
# def find_data(cls, id):
# with Session() as session:
# result = session.query(RECORDING_DATA_RAWS).first()
# return result
-60
View File
@@ -1,60 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
class SubjectData(Base):
__tablename__ = "subject_datas"
id = Column(Integer, primary_key=True)
subject_id = Column(Integer)
mode = Column(JSONB)
data = Column(JSONB)
user_auth = Column(JSONB)
meta = Column(String(255))
project = Column(String(255))
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_subject_data(cls, subject_id, project, meta, data):
with Session() as session:
subject = SubjectData(
subject_id = subject_id,
project = project,
meta= meta,
data = data
)
session.add(subject)
session.commit()
return subject
# @classmethod
# def check_name_duplicate(cls, collection_name, parent, n):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
# if result is None:
# return cls.generate_name(collection_name, n)
# else:
# new_num = n + 1
# # new_name = f"{collection_name}({new_num})"
# return cls.check_name_duplicate(collection_name, parent, new_num)
# @classmethod
# def generate_name(cls, collection_name, n):
# if n==0:
# return collection_name
# else:
# return f"{collection_name}({n})"
# @classmethod
# def find_collection(cls, collection_name, parent):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
# return result
+1 -1
View File
@@ -662,7 +662,7 @@ class CC2650Device(Device):
elif device_type == 'EISZeroOne':
i = 0
request_times = 0
while i < 13:
while i < 7:
try:
# send
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
+12 -23
View File
@@ -574,23 +574,20 @@ class DeviceManager(MasterDevice, Synchronized):
:param device: device ID or response info
:return: CompletedDevice, None if not found.
"""
try:
if isinstance(device, int):
for slave in self._device:
if slave.device_id == device:
return slave
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
except BaseException as e:
self.log_error('device not found', str(device))
elif isinstance(device, DeviceInfo):
for slave in self._device:
if device.match(slave):
return slave
return None
@@ -832,9 +829,6 @@ 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:
@@ -854,11 +848,6 @@ 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)
+117 -202
View File
@@ -1,12 +1,13 @@
import abc
import struct
import math
import numpy
from typing import Optional, TypeVar, Generic, Tuple, Dict, List, AnyStr
from datetime import datetime
from biopro.recording import RecordingData, RecordingFileDataFormat
import numpy as np
# from biopro.util.console import hex_line
T = TypeVar('T')
@@ -854,7 +855,7 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
'_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop', '_show_data')
'_mode_stop')
def __init__(self):
super().__init__()
@@ -869,8 +870,6 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
self._mode = 0
self._cycle_start_time = []
self._show_data = False
@property
def name(self) -> str:
return self.NAME
@@ -888,17 +887,17 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
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
ch2 = struct.unpack('<i', data[12:16])[0] # unit: uV
impedance = struct.unpack('<i', data[16:20])[0] # unit: mOm
if self._mode == 16:
voltage = impedance - ch2
else:
voltage = ch2
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]
@@ -922,11 +921,9 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
print("error timeStamp full data:", list(data), datetime.now(), '\n')
return None
else:
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('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
# '|', current, '|', voltage, '|', impedance,
# '|', cycle_number, '|', finishMode, '@', str(self.device))
# print('|', '{:10}'.format(time_stamp),
# '|', '{:4}'.format(delta),
@@ -955,9 +952,6 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
ret.append_data(1, voltage)
ret.append_data(2, impedance)
ret.append_data(3, cycle_number)
ret.append_data(4, notify_one)
ret.append_data(5, notify_two)
ret.append_data(6, notify_three)
# ret.append_data(4, battery)
# ret.append_data(5, elite_notify_times)
# ret.append_data(6, mem_cnt)
@@ -1346,8 +1340,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',
'_last_phase', '_first_phase_flag', '_show_data')
'cali_coeff', '_ac_amp', '_mode', '_freq_start', '_freq_stop',
'_freq_direction', '_last_phase', '_first_phase_flag')
def __init__(self, cali_coeff: bytes = None):
super().__init__()
@@ -1360,15 +1354,17 @@ class EISZeroOneDataDecoder(RecDataDecoder):
self._mode_stop = 0
self._cycle_start_time = []
self._ac_amp: int = 0
self._mode: int = 0
self._freq_start: int = 0
self._freq_stop: int = 0
self._freq_direction = 0
self._last_phase = 0
self._first_phase_flag = 1
self._cali_coeff: Optional[bytes] = None
self.cali_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)
@@ -1377,27 +1373,12 @@ 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
@@ -1408,95 +1389,51 @@ class EISZeroOneDataDecoder(RecDataDecoder):
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
index = 20
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]
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])
index = 40
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]
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])
#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])
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
#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])
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
#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])
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
#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])
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
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]
# 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)
print('cutoff_freq', cutoff_freq)
print('hsrtia_a', hsrtia_a)
print('hsrtia_b', hsrtia_b)
print('hsrtia_c', hsrtia_c)
print('phase_coeff')
print(phase_coeff)
print('phase_offset')
print(phase_offset)
# print('cutoff_freq', cutoff_freq)
# print('hsrtia_a', hsrtia_a)
# print('hsrtia_b', hsrtia_b)
# print('hsrtia_c', hsrtia_c)
# print('phase_para_a', phase_para_a)
# print('phase_para_b', phase_para_b)
cali_table.append((cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
cali_table.append((cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
return cali_table
else:
@@ -1526,14 +1463,9 @@ 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 = data[20+3]
finishMode = (d19 & 0x80) >> 7
ch4 = struct.unpack('<i', data[21+3:25+3])[0] # Amp[uV]
gain = (d19 & 0x0F)
finishMode = (d19 & 0x80) >> 7
notify_one = struct.unpack('<i', data[25+3:29+3])[0]
notify_two = struct.unpack('<i', data[29+3:33+3])[0]
notify_three = struct.unpack('<i', data[33+3:37+3])[0]
if time_stamp == 0:
self._start_return_data = True
@@ -1541,7 +1473,7 @@ class EISZeroOneDataDecoder(RecDataDecoder):
return None
if time_stamp != 0 and self._start_return_data == True:
if (self._mode == 0 or self._mode == 5):
if (self._mode == 0):
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)
@@ -1550,104 +1482,101 @@ 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 or self._mode == 5):
if self.cali_coeff is not None and self._mode == 0:
phase_para_a = []
phase_para_b = []
hsrtia_a = []
hsrtia_b = []
hsrtia_c = []
hsrtia_d = []
cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
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
if (self._mode == 0 or self._mode == 5):
if (self._mode == 0):
img = ch1
real = ch2
freq = ch3
fre_idx = 0
voltage_amp = round(ch4 / 1000) # Amp[mV]
# 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)
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2)
# if (gain == 3):
# current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag)
# else:
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain]
# 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] + hsrtia_c[gain]
# print(current)
# print(voltage_mag)
# print(hsrtia_a[gain])
# print(hsrtia_b[gain])
# print(hsrtia_c[gain])
if (current != 0):
# impedance[mOhm] = voltage_amp[mv] * 1000000 / 1.414213 / current[nA] #RMS=amp*SQRT(2), SQRT(2)=1.414213
impedance = voltage_amp * 707106.78 / current
# impedance = voltage_amp * 1000_000 / 1.414213 / current
impedance = voltage_amp * 707106.78 / current
else:
impedance = 0
raw_phase = math.atan2(img , real) * 180 / math.pi
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
if (freq >= 1000000): # 10000 Hz
fre_idx = 0
i = 0
elif (freq >= 10000): # 100 Hz
fre_idx = 1
i = 1
elif (freq >= 1000): # 10 Hz
fre_idx = 2
i = 2
elif (freq >= 1): # 0.01 Hz
fre_idx = 3
i = 3
ideal_raw_phase = phase_coeff[gain][fre_idx] /1e10 * freq + phase_offset[gain][fre_idx] / 1e6
ideal_raw_phase = phase_para_a[i] /1e10 * freq + phase_para_b[i] / 1e6
phase = raw_phase - ideal_raw_phase
phase = phase % 180 if phase % 180<=90 else phase % 180-180
# 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(phase - self._last_phase) >= 200):
phase -= 360
self._last_phase = phase
# 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)
imag_after_cal = impedance * math.sin(phase * math.pi / 180)
real_after_cal = impedance * math.cos(phase * math.pi / 180)
if self._show_data:
if (self._mode == 0 or self._mode == 5):
print('|', '{:10}'.format(time_stamp),
'|', '{:5}'.format(delta),
'|', '{:5}'.format(ch1), #raw_img
'|', '{:5}'.format(ch2), #raw_real
'|', '{:8}'.format(ch3 * 10), '[mHz]', #Frequency [mHz]
'|', '{:5}'.format(cycle_number), #cycle
'|', '{:5}'.format(round(imag_after_cal)), '[Ohm]', #Z_imag [Ohm]
'|', '{:5}'.format(round(real_after_cal)), '[Ohm]', #Z_real [Ohm]
'|', '{:5}'.format(round(impedance)), '[Ohm]', #Impedance [Ohm]
'|', '{:5}'.format(round(phase*1000)), '[mdegree]', #Phase [millidegree]
'|', '{:5}'.format(round(current)), '[nA]', #Current [nA]
'|', '{:1}'.format(gain), #gain
'|', '{:1}'.format(finishMode), #finishMode
'@', str(self.device), '|', flush = True)
print('|', '{:10}'.format(time_stamp),
'|', '{:5}'.format(delta),
'|', '{:5}'.format(notify_one),
'|', '{:5}'.format(notify_two),
'|', '{:5}'.format(notify_three),
'|', '{:5}'.format(voltage_amp), #amp[mV]
'|', flush = True)
pass
else:
print('|', '{:10}'.format(time_stamp),
'|', '{:5}'.format(delta),
'|', '{:5}'.format(ch1),
'|', '{:5}'.format(ch2),
'|', '{:5}'.format(ch3),
'|', '{:5}'.format(cycle_number),
'|', '{:1}'.format(gain),
'|', '{:1}'.format(finishMode),
'@', str(self.device), '|', flush = True)
pass
if (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 finishMode == True:
print("finishMode full data:", list(data), datetime.now())
@@ -1656,33 +1585,19 @@ class EISZeroOneDataDecoder(RecDataDecoder):
self._mode_stop = 0
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
if self._mode == 0 or self._mode == 5: #EIS Mode
ret.append_data(0, ch1) #raw_img
ret.append_data(1, ch2) #raw_real
if (self._mode == 0): #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) #cycle
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]
ret.append_data(7, round(phase*1000)) #Phase [millidegree]
ret.append_data(7, round(phase)) #Phase [degree]
ret.append_data(8, round(current)) #Current [nA]
ret.append_data(9, gain) #gain
#debug data
ret.append_data(10, notify_one)
ret.append_data(11, notify_two)
ret.append_data(12, notify_three)
ret.append_data(13, voltage_amp) #amp[mV]
ret.append_data(9, gain) #Gain Level
else:
if (self._mode == 1 or self._mode == 2 or self._mode == 3):
ch1 = ch1 * (-1)
if (self._mode == 4):
ch1 = ch1 * (-1)
ch3 = ch3 * (-1)
#CV Mode
else: #CV Mode
ret.append_data(0, ch1) #Iin [nA]
ret.append_data(1, ch2) #Vset [nV]
ret.append_data(2, ch3) #Vout [nV]
+6 -1
View File
@@ -651,6 +651,8 @@ class DeviceInstruction:
VIS_DEVICE_DONE = 0x20
"""identify device done"""
VIS_CC_ZERO = 0x40
VIS_STI = 0xC0
"""stimulation on virtual instruction"""
@@ -724,6 +726,7 @@ 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'
@@ -738,7 +741,7 @@ class DeviceCommonInstruction:
elif instruction == cls.START:
return '_data_format("TDC4VAF2")', '_notify(True)', 'VIS_STI', '_sync(True)'
elif instruction == cls.INTERRUPT:
return '_notify(False)', 'VIS_INT', '_sync(False)'
return '_sync(False)', '_notify(False)', 'VIS_INT'
elif instruction == cls.CLOSE:
return '_sync(False)', '_notify(False)', 'VIS_INT'
elif instruction == cls.CALL:
@@ -747,6 +750,8 @@ class DeviceCommonInstruction:
return 'VIS_DEVICE_DETECT',
elif instruction == cls.VIS_DEVICE_DONE:
return 'VIS_DEVICE_DONE',
elif instruction == cls.VIS_CC_ZERO:
return 'VIS_CC_ZERO',
elif instruction == cls.RECORD:
return 'VIS_STARTR',
elif instruction == cls.RECORD_ALL:
-2
View File
@@ -283,7 +283,6 @@ class InternalInstruction(SingleInstruction):
PREDEFINED_SET = '_set'
PREDEFINED_CDR = '_cdr'
PREDEFINED_DISABLE_CACHE = '_disable_cache'
PREDEFINED_IDLE = '_idle'
PREDEFINED = (
PREDEFINED_SLEEP,
@@ -295,7 +294,6 @@ class InternalInstruction(SingleInstruction):
PREDEFINED_SET,
PREDEFINED_CDR,
PREDEFINED_DISABLE_CACHE,
PREDEFINED_IDLE,
)
__slots__ = ('_expr', '_para')
+2 -23
View File
@@ -968,7 +968,7 @@ class CompletedDevice(Device):
"""
__slots__ = ('_master', '_device_id', '_device', '_library', '_context',
'_parameter', '_configuration', '_lock', '_feature_mask',
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project')
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status')
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
"""
@@ -986,8 +986,6 @@ class CompletedDevice(Device):
# device status ( 0: idle, 1: working, 2: error, 3: power off)
self._status = 0
# device be occupied by project
self._occupied_by_project = None
# context
s1 = library.constant
@@ -1034,7 +1032,7 @@ class CompletedDevice(Device):
@property
def mac_address_in_str(self) -> str:
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address).upper()
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address)
@property
def device(self) -> Device:
@@ -1084,14 +1082,6 @@ class CompletedDevice(Device):
def status(self, new_status):
self._status = new_status
@property
def occupied_by_project(self) -> str:
return self._occupied_by_project
@occupied_by_project.setter
def occupied_by_project(self, new_occupied_by_project):
self._occupied_by_project = new_occupied_by_project
# device parameter getter/setter
def parameters(self) -> List[str]:
@@ -1115,8 +1105,6 @@ 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)
@@ -1140,11 +1128,6 @@ 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
@@ -1292,9 +1275,6 @@ class CompletedDevice(Device):
def central_version_get(self) -> Optional[list]:
return self._device.central_version_get()
def save_data_to_subject(self, project, meta, device, subject_id):
self._master._handler.save_data_to_subject(project, meta, device, subject_id)
# utility method
@@ -1316,7 +1296,6 @@ class CompletedDevice(Device):
'recording_file_name': self.recording_file_name,
'library_name': self._library.name,
'library_version': str(self._library.version),
'occupied_by_project': self._occupied_by_project,
'configuration': self.configuration.as_json(list_hide=True),
}
+7 -21
View File
@@ -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', '_pin_busy_value')
'_head_wrong_cnt')
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] * 64
self._tx_buffer_header = [0] * 19
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
# memory control pin
self.pin_busy: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_BZY)
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True)
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,7 +62,6 @@ 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
@@ -99,14 +98,6 @@ 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
@@ -225,9 +216,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
return
def recv_memory(self, device: int) -> Optional[bytes]:
# self.pin_busy.output(False)
# print('mem_req==ram_sel,[', self._pin_mem_req_value[device], ',', self._pin_ram_sel_value[device], ']')
self.pin_busy.output(False)
rx = []
@@ -311,9 +300,6 @@ 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)
@@ -429,9 +415,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)
+1 -1
View File
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
self._serial = serial.Serial(self._port,
baudrate=self._baudrate,
timeout=0,
writeTimeout=1)
writeTimeout=0.01)
# deprecate function name which change at version 3.0
self._serial.flushInput()
self._serial.flushOutput()
-8
View File
@@ -24,11 +24,3 @@ class Action():
@property
def condition(self):
return self._condition
def as_json(self):
return {
'id': self._id,
'type': self._type,
'target': self._target,
'condition': self._condition
}
+12 -61
View File
@@ -45,8 +45,8 @@ class Condition():
# print(operator, x, y)
cases = {
"equal": lambda a, b: a == b,
"bigger": lambda a, b: a >= b,
"smaller": lambda a, b: a <= b,
"bigger": lambda a, b: a > b,
"smaller": lambda a, b: a < b,
}
return cases[operator](x, y)
@@ -56,8 +56,7 @@ class Condition():
return getattr(self, self.type)(**kwargs)
def absolute_time(self, **kwargs):
# now = int(time())
now = round(time(), 1)
now = int(time())
time_condition = round(self.datetime_to_timestamp(self.str_to_datetime(self._value)))
return self.compareWith(self.comparsion, now, time_condition)
@@ -66,80 +65,32 @@ class Condition():
project_start_time = kwargs['project_start_time']
delay_time = kwargs['delay_time']
# time_diff = int(time() - project_start_time - delay_time)
time_diff = round(time() - project_start_time - delay_time, 1)
return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
time_diff = int(time() - project_start_time - delay_time)
return self.compareWith(self.comparsion, time_diff, int(self._value))
def after_task_run(self, **kwargs):
# print('relative_time_from_task', kwargs['task_start_time'],kwargs['delay_time'])
# print('relative_time_from_task', kwargs,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))
time_diff = int(time() - task_start_time - delay_time)
# print('time_diff', time_diff)
return self.compareWith(self.comparsion, time_diff, int(self._value))
def device(self, **kwargs):
print('device')
""" def previous_task_done(self, **kwargs):
def previous_task_done(self, **kwargs):
running_task = kwargs['running_task']
if running_task.status == 2 and self._active == False:
self._active = True
return True
return False """
def previous_task_done(self, **kwargs):
running_task = kwargs['running_task']
self_task = kwargs['self_task']
# if running_task != None and self_task != None:
# print('\nprevious_task_done: ', running_task.status, ' ', self._active)
if running_task != self_task:
if running_task == None:
return True
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False
def until_button_trigger(self, **kwargs):
running_task = kwargs['running_task']
if running_task != None:
if running_task.button_trigger == True:
running_task.button_trigger = False
return True
return False
""" def cycle(self, **kwargs):
running_task = kwargs['running_task']
self_task = kwargs['self_task']
if running_task != self_task:
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False """
def str_to_datetime(self, time_str):
return datetime.strptime(time_str,'%Y-%m-%dT%H:%M')
def datetime_to_timestamp(self, date):
return datetime.timestamp(date)
def as_json(self):
return {
'id': self._id,
'type': self._type,
'comparsion': self._comparsion,
'value': self._value,
'active': self._active
}
return datetime.timestamp(date)
+1 -6
View File
@@ -22,7 +22,6 @@ class Instruction():
self._start_instruction = list(map(lambda ins: self._instruction_set[ins] ,['set_file_name', 'set_parent', 'set_parameter', 'call_instruction']))
self._stop_instruction = list(map(lambda ins: self._instruction_set[ins] ,['call_instruction']))
self._idle_instruction = []
@property
def start(self) -> list:
@@ -30,8 +29,4 @@ class Instruction():
@property
def stop(self) -> list:
return self._stop_instruction
@property
def idle(self) -> list:
return self.idle_instruction
return self._stop_instruction
+29 -222
View File
@@ -1,7 +1,6 @@
import sys
import json
import threading
import logging
from time import time, sleep
from datetime import datetime
@@ -15,20 +14,17 @@ from .instruction import Instruction
from biopro.device.manager import DeviceManager
from biopro.text import *
from biopro.db.base import Session
from biopro.db.collection import Collection
key_list = {
'deviceList': 'device',
}
class Project(threading.Thread):
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, log_verbose = None, name="project"):
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, name="project"):
super(Project, self).__init__(name = name)
self._project = project
self._device_manager = device_manager
self._mqtt_thread = mqttThread
self._time_interval = 0.1
self._time_interval = 1
self._start_time = None
self._end_time = None
@@ -37,7 +33,7 @@ class Project(threading.Thread):
self._name = None
self._desc = None
self._device = None
self._complete_device = {}
self._complete_device = []
self._status = 0
self._instruction_set = Instruction()
@@ -45,46 +41,16 @@ class Project(threading.Thread):
self._task_manager = None
self._cycle = []
self._count = 1 #流水號
self._project_meta_id = -1
self._subject = []
self.log_verbose = log_verbose
self._logger = logging.getLogger('project')
self._logger.setLevel('DEBUG')
self._formatter = logging.Formatter('[%(asctime)s.%(msecs)03d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
self._formatter_with_nothing = logging.Formatter('%(message)s')
self.setup_project(project)
self.setup_device(self._device)
# create log file handler
fh = logging.FileHandler(f'/home/pi/logger/project/{self.uuid}.log', mode="w")
fh.setFormatter(self._formatter)
self._logger.addHandler(fh)
default_name = 'admin'
default_parent = {"folder": [1]}
collection = Collection.find_collection(default_name, default_parent)
parent = {"folder": [collection.id]}
# create project folder
folder_name_duplicate = False
if len(self._subject) > 0:
folder_name_duplicate = True
collection = Collection.create_collection(self.name, parent, folder_name_duplicate)
self.setup_collection(collection)
def setup_project(self, project):
for (key, value) in project.items():
if key in key_list.keys():
key = key_list[key]
if key == 'task':
self._task_manager = TaskManager(project['task'], project['cycle'])
self._task_manager = TaskManager(project['task'])
elif key == 'uuid':
pass
else:
@@ -92,13 +58,8 @@ class Project(threading.Thread):
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
def setup_collection(self, collection):
self._task_manager.create_collection(collection)
complete_device = self._device_manager.get_device(device['connectDevice']['device_address'])
self._complete_device.append(complete_device)
@property
def id(self) -> int:
@@ -107,22 +68,6 @@ class Project(threading.Thread):
@id.setter
def id(self, new_id):
self._id = new_id
@property
def project_meta_id(self) -> int:
return self._project_meta_id
@project_meta_id.setter
def project_meta_id(self, new_project_meta_id):
self._project_meta_id = new_project_meta_id
@property
def subject(self) -> object:
return self._subject
@subject.setter
def subject(self, new_subject):
self._subject = new_subject
@property
def uuid(self) -> str:
@@ -139,14 +84,6 @@ class Project(threading.Thread):
@name.setter
def name(self, new_name):
self._name = new_name
@property
def cycle(self) -> list:
return self._cycle
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
@property
def desc(self) -> str:
@@ -180,28 +117,9 @@ class Project(threading.Thread):
def mqtt_thread(self):
return self._mqtt_thread
@property
def running_task(self):
return self._task_manager.running_task
def get_device_parameter_set(self, device_address):
parameter_set = self._task_manager.running_task.parameter_set
return next((x for x in parameter_set if parameter_set[x]['target'] == device_address), None)
def get_cycle(self, task):
for index, _cycle in enumerate(self.cycle):
if task.uuid in _cycle['range']:
return _cycle
def run(self):
# project status change running (1)
self._status = 1
# save start time
self._start_time = time()
# saving & broadcast message
self._logger.info('Project ' + self.name + ' start')
self.log_verbose('Project ' + self.name + ' start')
self.mqtt_thread.broadcast_command('project:' + self._name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
while not self._stop_flag :
@@ -212,114 +130,47 @@ class Project(threading.Thread):
for task in check_list:
if task != None:
now = time()
# print('round task', task.name)
# print('running task', self._task_manager.running_task.name, self._task_manager.running_task.status)
# if self._task_manager.prev_task != None:
# print('previous_task', self._task_manager.prev_task.name, self._task_manager.prev_task.status)
match_condition_list = task.check_condition(
project_start_time = self._start_time,
delay_time = delay_time,
running_task= self._task_manager.running_task,
previous_task = self._task_manager.prev_task,
self_task = task
previous_task = self._task_manager.prev_task
)
# print('match_condition_list', match_condition_list)
for condition in match_condition_list:
match_action_list = task.get_match_action(condition.id)
print('match_action_list', match_action_list, match_action_list)
for action in match_action_list:
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])
# print('match_action', action.type, action.target)
if action.type == 'start' and task.status != 1:
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"]} -----------')
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
if self._task_manager.running_task != None:
if self._task_manager.running_task.uuid == task.uuid and action.type == 'cycle' and condition.type == 'after_task_run':
self._task_manager.running_task.stop()
if action.type == 'start':
if task.status != 1:
self._task_manager.set_running_task(task)
self._logger.info(f'Task {str(self._task_manager.running_task.name)} start')
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# elif action.type == 'stop':
# self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# self._count += 1
# if self.check_running_task_not_run() == True:
# self._task_manager.running_task.stop()
elif action.type == 'idle':
self._task_manager.running_task.stop()
# elif action.type == 'stop':
# self._task_manager.running_task.stop()
instruction_set = None
if action.target is not None:
device = self._complete_device[action.target]
if ((action.type == 'start' and device.status == 0) or (action.type == 'stop' and device.status == 1)):
self._logger.info(f'Device {device.mac_address_in_str} {action.type}')
self.log_verbose('Project' + self.name + 'Task ' + task.name + ' match_condition ' + condition.type + ' trigger_action ' + action.type + ' ' + str(action.target))
task_info = task.get_task_info(action)
instruction_set = getattr(self._instruction_set, action.type, None)
# 檔名修正
# device
task_info['file_name'] += '#' + device.mac_address_in_str[12:].upper()
# 流水號
task_info['file_name'] += '#' + str(self._count)
# 添加cycle資訊
if len(self.cycle) > 0:
index = self._task_manager.get_index_by_task(task)
# get list of cycle determine by index of task
filtered = list(filter(lambda info: self._task_manager.get_index_by_uuid(info['range'][0]) < index and self._task_manager.get_index_by_uuid(info['range'][1]) > index, self.cycle))
if len(filtered) == 0:
pass
elif len(filtered) == 1:
if filtered[0]['useID'] == True:
task_info['file_name'] += '#' + str(filtered[0]['id'])
else:
task_info['file_name'] += '#' + str(filtered[0]['name']) + '-' + str(filtered[0]['count'])
else:
# if multi cycle, then sort by range from task index to cycle start index, then loop concat filename
filtered.sort(key=lambda info: abs(self._task_manager.get_index_by_uuid(info['range'][0]) - index))
for cycle_info in filtered:
if cycle_info['useID'] == True:
task_info['file_name'] += '#' + str(cycle_info['id'])
else:
task_info['file_name'] += '#' + str(cycle_info['name']) + '-' + str(cycle_info['count'])
self.log_verbose('file name ' + task_info['file_name'])
if instruction_set != None and self.get_device_parameter_set(action.target) != None:
for instruction in instruction_set:
print('instruction 1', device, instruction, datetime.now())
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
target=getattr(device, instruction['method'])(*args)
print('instruction 2', device, instruction, datetime.now())
if (action.type == 'stop'):
if (len(self._subject) > 0):
target=getattr(device, "save_data_to_subject")(self.id, self.project_meta_id, device, self._subject[0])
if action.type == 'start':
self._count += 1
device = self._complete_device[action.target]
task_info = task.get_task_info(action)
instruction_set = getattr(self._instruction_set, action.type, None)
# print('instruction_set',instruction_set)
if instruction_set != None:
for instruction in instruction_set:
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
threading.Thread(target=getattr(device, instruction['method'])(*args))
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.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()
self.close()
if self._time_interval - delay_time > 0:
sleep(self._time_interval - delay_time)
@@ -329,19 +180,14 @@ class Project(threading.Thread):
pass
def stop(self):
for device in self._complete_device:
self._complete_device[device].occupied_by_project = None
self._task_manager.running_task.stop()
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._status = 2
self._end_time = time()
self._stop_flag = True
self._logger.info('Project ' + self.name + ' stop')
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
def close(self):
for device in self._complete_device:
self._complete_device[device].occupied_by_project = None
self._status = 2
self._end_time = time()
self._stop_flag = True
@@ -354,43 +200,17 @@ class Project(threading.Thread):
return False
return True
def set_content(self, content):
self.running_task.button_trigger = True
def set_cycle(self, index, content):
# change cycle name
for key in content:
self.cycle[index][key] = content[key]
# change task name
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][0]).name = content['name']
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][1]).name = content['name']
def check_running_task_not_run(self):
# if no running task
if self._task_manager.running_task == None:
return False
# if running is cycle then no need to stop by device
if self._task_manager.running_task.type == 'cycle':
return False
for key in self._task_manager.running_task.action:
# print('action key', key, self._task_manager.running_task, self._task_manager.running_task.action[key])
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'stop':
return False
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'idle':
return False
for device in self._task_manager.running_task.device:
if self._complete_device[device].status == 1:
return False
return True
def as_json(self):
running_task = None
if self._task_manager.running_task is not None:
running_task = self._task_manager.running_task.as_json()
data = {
'id': self._id,
'name': self._name,
@@ -399,19 +219,6 @@ class Project(threading.Thread):
'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,
'running_task': self._task_manager.running_task.as_json()
}
return data
+2 -11
View File
@@ -9,14 +9,13 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':'))
class ProjectManager():
def __init__(self, device_manager: DeviceManager, mqtt_thread=None, log_verbose = None) :
def __init__(self, device_manager: DeviceManager, mqtt_thread=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, self.log_verbose)
new_project = Project(project, self._device_manager, self._mqtt_thread)
self._project_list.append(new_project)
return new_project
@@ -38,11 +37,3 @@ class ProjectManager():
def stop_project(self, project):
_project = self.get(project)
_project.stop()
def set_project(self, project_uuid, content):
_project = self.get(project_uuid)
_project.set_content(content)
def set_project_cycle(self, project_uuid, index, content):
_project = self.get(project_uuid)
_project.set_cycle(index, content)
+2 -62
View File
@@ -12,39 +12,29 @@ key_list = {
class Task:
def __init__(self, task):
self._id = None
self._uuid = None
self._type = None
self._name = None
self._parent = None
self._cycle = None
self._cycle_count = 0
self._cycle_next = None
self._cycle_next_uuid = None
self._device = None
self._event = None
self._trigger = None
self._parameter_set = None
self._condition = None
self._action = None
# -1: init 0: start(idle), 1: run, 2: close(idle)
# -1: initial 0: start(idle), 1: running, 2: close(idle)
self._status = 0
self._next = None
# action & condition info
self._condition_list: List[Condition] = []
self._action_list: List[Action] = []
self._instruction_list = []
self._record_list = []
# time info
self._start_time = []
self._idle_time = []
self._end_time = []
self._period = None
# trigger info
self._button_trigger = False
self.load_task(task)
def load_task(self, task) -> None:
@@ -84,14 +74,6 @@ class Task:
@uuid.setter
def uuid(self, new_uuid):
self._uuid = new_uuid
@property
def type(self):
return self._type
@type.setter
def type(self, new_type):
self._type = new_type
@property
def name(self):
@@ -118,31 +100,6 @@ class Task:
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
# TODO: not sure needed?
@property
def cycle_count(self) -> int:
return self._cycle_count
@cycle_count.setter
def cycle_count(self, new_cycle_count):
self._cycle_count = new_cycle_count
@property
def cycle_next(self) -> str:
return self._cycle_next
@cycle_next.setter
def cycle_next(self, new_cycle_next):
self._cycle_next = new_cycle_next
@property
def cycle_next_uuid(self) -> str:
return self._cycle_next_uuid
@cycle_next_uuid.setter
def cycle_next_uuid(self, new_cycle_next_uuid):
self._cycle_next_uuid = new_cycle_next_uuid
@property
def device(self) -> dict:
@@ -220,14 +177,6 @@ class Task:
def end_time(self) -> List:
return self._end_time
@property
def button_trigger(self) -> List:
return self._button_trigger
@button_trigger.setter
def button_trigger(self, button_trigger):
self._button_trigger = button_trigger
def new_start_time(self):
self._start_time.append(time())
@@ -258,10 +207,6 @@ class Task:
def stop(self):
self.status = 2
def reset(self):
self.status = -1
# self.status = 0
def get_match_action_list(self, match_condition_list):
return map(lambda condition: [x for x in self._action_list if condition.id in x.get_condition_list()], match_condition_list)
@@ -285,7 +230,7 @@ class Task:
return {
'device': action.target,
'parameter': self.get_parameter_set_by_device(action.target),
'file_name': self._name,
'file_name': self._name + '-' + str(action.target),
'parent': self.parent,
'instruction': _type
}
@@ -295,12 +240,7 @@ class Task:
'id': self.id,
'name': self.name,
'parent': self.parent,
'type': self.type,
'uuid': self.uuid,
'cycle': self.cycle,
'cycle_count': self.cycle_count,
'cycle_next': self.cycle_next,
'cycle_next_uuid': self.cycle_next_uuid,
'device': self.device,
'event': self.event,
'trigger': self.trigger,
+3 -96
View File
@@ -5,7 +5,6 @@ from xml.dom.expatbuilder import parseString
import paho.mqtt.client as mqtt
from biopro.text import *
from .task import Task
from biopro.db.collection import Collection
_RUNTIME_COMPILE = False
@@ -13,12 +12,11 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':'))
class TaskManager():
def __init__(self, task_list, cycle_list):
def __init__(self, task_list):
self._task_list = []
self._next_task = []
self._prev_task = None
self._running_task = None
self._cycle_list = cycle_list
self.load_task_list(task_list)
@@ -46,35 +44,6 @@ class TaskManager():
def next_task(self):
return self._next_task
def get_task_by_index(self, index):
return self._task_list[index]
def get_task_by_uuid(self, uuid):
return next((x for x in self.task_list if x.uuid == uuid), None)
def get_index_by_task(self, task):
return next((i for i, x in enumerate(self.task_list) if x.uuid == task.uuid), None)
def get_index_by_uuid(self, uuid):
return next((i for i, x in enumerate(self.task_list) if x.uuid == uuid), None)
def check_task_is_cycle_start(self, task):
for index, cycle in enumerate(self._cycle_list):
if cycle['range'][0] == task.uuid:
return index
def check_task_is_cycle_end(self, task):
for index, cycle in enumerate(self._cycle_list):
if cycle['range'][1] == task.uuid:
return index
def check_task_in_cycle(self, task_index):
for index, cycle in enumerate(self._cycle_list):
if self.get_index_by_uuid(cycle['range'][0]) <= task_index:
if self.get_index_by_uuid(cycle['range'][1]) >= task_index:
return True
return False
@property
def check_list(self):
return [self._running_task, *self._next_task]
@@ -88,8 +57,7 @@ class TaskManager():
task = Task(task)
self._task_list.append(task)
# original version
""" def set_running_task(self, task):
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:
@@ -112,70 +80,9 @@ class TaskManager():
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
self._next_task.append(_task)
except RuntimeError as e:
print(e) """
def set_running_task(self, task):
try:
# if there is task running & same task active ,then reject
if self._running_task != None and self._running_task.uuid == task.uuid:
return False
# save task
self._prev_task = self._running_task
# clear next task list
self._next_task.clear()
# set task to running_task
self._running_task = task
self._running_task.run()
# if previous task is still running, then need to close
if self._prev_task != None:
if self._prev_task.status == 1:
self._prev_task.stop()
# if reach cycle end, count < max, then go to cycle start
cycle_start_index = self.check_task_is_cycle_start(task)
cycle_index = self.check_task_is_cycle_end(task)
if cycle_index is None:
# print('next', self._running_task.name, self._running_task.next)
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
# print('self._next_task', self._next_task)
else:
# print('cycle', self._cycle_list[cycle_index])
cycle = self._cycle_list[cycle_index]
if int(cycle['count']) < int(cycle['max']):
self._next_task.append(self.get_task_by_uuid(cycle['range'][0]))
# cycle['count'] += 1
else:
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
# cycle['count'] = 1
if cycle_start_index != None:
cycle = self._cycle_list[cycle_start_index]
if int(cycle['count']) < int(cycle['max']):
cycle['count'] += 1
else:
cycle['count'] = 1
except RuntimeError as e:
print(e)
def get_task(self, task_id):
return self._task_list[task_id]
def create_collection(self, parent):
for index, task in enumerate(self._task_list):
if self.check_task_in_cycle(index) == True:
if task.type == '':
collection = Collection.create_collection(task.name, {"folder": [parent.id]}, False)
task.parent = {"folder": [collection.id]}
else:
task.parent = {"folder": [parent.id]}
+60 -33
View File
@@ -20,6 +20,11 @@ from statistics import mean
import random
# from numba import jit
from .lttb import largest_triangle_three_buckets
import math
from scipy import signal
from copy import copy
def json_stringify(o) -> str:
@@ -118,7 +123,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', '_project_id')
'_raw_serial_number', '_mini_serial_number', '_device_id')
def __init__(self, filepath: Union[str, Path], data_format: bytes = None, id_db = 0, database = None):
if isinstance(filepath, str):
@@ -153,7 +158,6 @@ class RecordingMetaFile(JsonSerialize):
self._parent = ''
self._recording_file_name = ''
self._device_id = -1
self._project_id = None
# recording parameter
self._configuration = None
@@ -298,7 +302,6 @@ class RecordingMetaFile(JsonSerialize):
'uuid': str(self._file_uuid),
'data_format': 'rec',
'device': self._device,
'project': self._project_id,
}
if len(self._parent) > 0:
@@ -464,7 +467,7 @@ class RecordingMetaFile(JsonSerialize):
def parameter(self) -> str:
return self._parameter
@parameter.setter
@device.setter
def parameter(self, parameter):
self._parameter = parameter
return None
@@ -473,7 +476,7 @@ class RecordingMetaFile(JsonSerialize):
def parent(self) -> str:
return self._parent
@parent.setter
@device.setter
def parent(self, parent):
self._parent = parent
@@ -481,7 +484,7 @@ class RecordingMetaFile(JsonSerialize):
def recording_file_name(self) -> str:
return self._recording_file_name
@recording_file_name.setter
@device.setter
def recording_file_name(self, recording_file_name):
self._recording_file_name = recording_file_name
@@ -494,15 +497,6 @@ 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]:
@@ -1026,7 +1020,7 @@ class RecordingFileWriter:
'_mini_scale_list', '_time_real_time', '_data_rl', '_data_db',
'_raw_save', '_mini_save', '_data_time_ch', '_data_value_ch_for_rl',
'_data_time_ch_for_rl', '_device_id', '_send_data', '_data_mqtt_ch', '_id_db_save', '_raw_create_not_done',
'_mini_create_not_done')
'_mini_create_not_done', '_data_all')
def __init__(self, meta: RecordingMetaFile, device_id, database = None):
self._meta = meta
@@ -1086,6 +1080,8 @@ class RecordingFileWriter:
self._data_time_ch = {}
self._id_db_save = {}
self._data_all = {}
# mini data
self._data_mini_ch = {}
@@ -1238,17 +1234,17 @@ class RecordingFileWriter:
def get_data_iter(self, d, mqtt_thread):
# print('****d size', d.data_size)
for t, c, v in d.entry_iter():
# print(t,c,v)
if c in self._data_db:
self._data_all[c].append([int(t), v])
### send real-time
if len(self._data_rl[c]) > 0 and self._send_data[c]:
self._data_rl[c].append(str(int(t)))
mes = ' '.join(self._data_rl[c])
# self._data_mqtt_ch[c] = self._data_rl[c].copy()
# self._data_mqtt_ch[c].append(str(int(t)))
# print('message1', mes)
mqtt_thread[c].on_message(mes)
self._data_rl[c].clear()
self._send_data[c] = False
### send real-time
sample_rate_rl = 1
# rec data
@@ -1261,40 +1257,35 @@ class RecordingFileWriter:
self._data_value_ch[c].append(int(v))
self._data_value_ch_for_rl[c].append(int(v))
self._data_time_ch_for_rl[c].append(int(t))
# self._data_time_ch[c].append(int(t))
# print('self._data_value_ch[c]', self._data_value_ch[c])
# print('self._data_value_ch_for_rl[c]', self._data_value_ch_for_rl[c])
# print('self._data_time_ch_for_rl[c]', self._data_time_ch_for_rl[c])
for scale in self._mini_scale_list:
if self._data_mini_ch[c][str(scale)]['start_time'] is None:
self._data_mini_ch[c][str(scale)]['start_time'] = str(int(t))
# print('len(self._data_value_ch_for_rl[c])', len(self._data_value_ch_for_rl[c]))
# print('sample_rate_rl:', sample_rate_rl)
if len(self._data_value_ch_for_rl[c]) >= sample_rate_rl:
if len(self._data_value_ch_for_rl[c]) == 1:
if len(self._data_rl[c]) == 0:
self._data_rl[c].append(str(int(t)))
# self._data_rl[c].append(str(self._data_time_ch_for_rl[c][0]))
self._data_rl[c].append(str(self._data_value_ch_for_rl[c][0]))
else:
if len(self._data_rl[c]) == 0:
self._data_rl[c].append(str(int(t)))
# self._data_rl[c].append(str(self._data_time_ch_for_rl[c][0]))
# self._data_rl[c].append(str(self._data_value_ch_for_rl[c][0]))
_max = max(self._data_value_ch_for_rl[c])
_max_index = self._data_value_ch_for_rl[c].index(_max)
_min = min(self._data_value_ch_for_rl[c])
_min_index = self._data_value_ch_for_rl[c].index(_min)
# _mean = mean(self._data_value_ch_for_rl[c])
# _first_time = self._data_time_ch_for_rl[c][0]
# _last_time = self._data_time_ch_for_rl[c][-1]
# print('_max, _max_index, _min, _min_index', _max, _max_index, _min, _min_index)
if _max_index < _min_index:
# self._data_rl[c].append(str(_first_time))
self._data_rl[c].append(str(_max))
# self._data_rl[c].append(str(_last_time))
self._data_rl[c].append(str(_min))
else:
# self._data_rl[c].append(str(_first_time))
self._data_rl[c].append(str(_min))
# self._data_rl[c].append(str(_last_time))
self._data_rl[c].append(str(_max))
self._data_value_ch_for_rl[c].clear()
@@ -1303,9 +1294,6 @@ class RecordingFileWriter:
# mini picture
if len(self._data_value_ch[c]) >= 10:
self._data_mini_ch[c]['10']['mean'].append( int(mean(self._data_value_ch[c][0:9])) )
# self._data_mini_ch[c]['10']['random'].append( str(self._data_value_ch[c][random.randint(0,9)]) )
# _bar = self.get_bar(self._data_value_ch[c], None)
# self._data_mini_ch[c]['10']['bar'].extend(_bar)
self._data_value_ch[c].clear()
if int(len(self._data_mini_ch[c]['10']['mean']) / 10) - self._data_mini_ch[c]['10']['dec'] > 0:
self._data_mini_ch[c]['100']['mean'].append( int(mean(self._data_mini_ch[c]['10']['mean'][-10:])) )
@@ -1327,6 +1315,13 @@ class RecordingFileWriter:
self._data_db[c].append(str(int(t)))
self._data_db[c].append(str(v))
self._time_now = int(t)
# print('self._data_rl',self._data_rl)
# print('self._data_db', self._data_db)
# print('self._data_value_ch', self._data_value_ch)
# print('self._data_value_ch_for_rl', self._data_value_ch_for_rl)
# print('self._data_time_ch_for_rl', self._data_time_ch_for_rl)
# print('self._data_time_ch', self._data_time_ch)
# print('self._id_db_save', self._id_db_save)
return
# @calculate_time(1)
@@ -1374,6 +1369,7 @@ class RecordingFileWriter:
self._data_db[ch] = []
self._time[ch] = 0
self._time_real_time[ch] = 0
self._data_all[ch] = []
if len(self._data_mini_ch) == 0:
for ch in self._channel_list:
self._data_mini_ch[ch] = {}
@@ -1387,6 +1383,37 @@ class RecordingFileWriter:
}
self.get_data_iter(d, mqtt_thread)
print('data', len(self._data_all[0]))
test = []
# for ch in self._data_all:
# if len(self._data_all[ch]) <= 1000:
# print('math.ceil(len(self._data_all[ch]) / 10) + 1', math.ceil(len(self._data_all[ch]) / 10) + 1)
# test = largest_triangle_three_buckets(self._data_all[ch], math.ceil(len(self._data_all[ch]) / 10) + 1)
# else:
# self._data_all[ch] = largest_triangle_three_buckets(self._data_all[ch], 1000)
# test = self._data_all[ch]
# print('test', test)
# a = [' '.join(list(map(str, b))) for b in test]
# print('a', a)
# mes = ' '.join(a)
# mqtt_thread[50+ch].on_message(mes)
for ch in self._data_all:
if len(self._data_all[ch]) <= 1000:
self._data_all[ch] = signal.savgol_filter(self._data_all[ch], 32, 3)
else:
self._data_all[ch] = signal.savgol_filter(self._data_all[ch], 32, 3)
print('test', test)
a = [' '.join(list(map(str, b))) for b in self._data_all[ch]]
print('a', a)
mes = ' '.join(a)
mqtt_thread[50+ch].on_message(mes)
if len(self._recording_file_dict) > 0:
for ch in self._data_db.keys():
+108
View File
@@ -0,0 +1,108 @@
"""
The MIT License (MIT)
Copyright (c) 2015 Olivier Devoisin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import math
class LttbException(Exception):
pass
def largest_triangle_three_buckets(data, threshold):
"""
Return a downsampled version of data.
Parameters
----------
data: list of lists/tuples
data must be formated this way: [[x,y], [x,y], [x,y], ...]
or: [(x,y), (x,y), (x,y), ...]
threshold: int
threshold must be >= 2 and <= to the len of data
Returns
-------
data, but downsampled using threshold
"""
# Check if data and threshold are valid
if not isinstance(data, list):
raise LttbException("data is not a list")
if not isinstance(threshold, int) or threshold <= 2 or threshold >= len(data):
raise LttbException("threshold not well defined")
for i in data:
if not isinstance(i, (list, tuple)) or len(i) != 2:
raise LttbException("datapoints are not lists or tuples")
# Bucket size. Leave room for start and end data points
every = (len(data) - 2) / (threshold - 2)
a = 0 # Initially a is the first point in the triangle
next_a = 0
max_area_point = (0, 0)
sampled = [data[0]] # Always add the first point
for i in range(0, threshold - 2):
# Calculate point average for next bucket (containing c)
avg_x = 0
avg_y = 0
avg_range_start = int(math.floor((i + 1) * every) + 1)
avg_range_end = int(math.floor((i + 2) * every) + 1)
avg_rang_end = avg_range_end if avg_range_end < len(data) else len(data)
avg_range_length = avg_rang_end - avg_range_start
while avg_range_start < avg_rang_end:
avg_x += data[avg_range_start][0]
avg_y += data[avg_range_start][1]
avg_range_start += 1
avg_x /= avg_range_length
avg_y /= avg_range_length
# Get the range for this bucket
range_offs = int(math.floor((i + 0) * every) + 1)
range_to = int(math.floor((i + 1) * every) + 1)
# Point a
point_ax = data[a][0]
point_ay = data[a][1]
max_area = -1
while range_offs < range_to:
# Calculate triangle area over three buckets
area = math.fabs(
(point_ax - avg_x)
* (data[range_offs][1] - point_ay)
- (point_ax - data[range_offs][0])
* (avg_y - point_ay)
) * 0.5
if area > max_area:
max_area = area
max_area_point = data[range_offs]
next_a = range_offs # Next a is this b
range_offs += 1
sampled.append(max_area_point) # Pick this point from the bucket
a = next_a # This a is the next a (chosen b)
sampled.append(data[len(data) - 1]) # Always add last
return sampled
+18 -36
View File
@@ -4,6 +4,7 @@ from time import time, sleep
from typing import Iterable
from datetime import datetime
import gc
import base64
from biopro.data import *
@@ -26,6 +27,7 @@ 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
@@ -63,7 +65,7 @@ class DataServer(SocketServer, DataAPI):
"""
global _FLAG_DATA_LOST_STATS_
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=20)
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=3)
data_options = DataServerOptions.get_options(*options)
@@ -315,8 +317,7 @@ class DataServer(SocketServer, DataAPI):
def update_device_configuration(self,
device: str,
meta_file: Union[str, Path, RecordingMetaFile],
data_format: Union[AnyStr, DataDecodeFormat],
project_info: str):
data_format: Union[AnyStr, DataDecodeFormat]):
# meta file
device_id = -1
@@ -344,8 +345,6 @@ 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']
@@ -355,22 +354,13 @@ class DataServer(SocketServer, DataAPI):
# meta_file.parameter = _parameter
# meta_file.parent = _parent
# meta_file.recording_file_name = _recording_file_name
device_id = int(json.loads(device)['device_id'])
if device_id < 0:
raise ValueError('illegal device ID : ' + str(device_id))
self.log_verbose('device ID', device_id)
# project binding meta file
# project_id = None
# _project = None
# if project_info != None:
# _project = json.loads(project_info)
# self.database_process.put_queue(['project_insert', device_id, _project])
# result = self._queue_ds_dict[int(device_id)].get()
# if result[0] == 'project_id':
project_id = project_info
# while len(self._configurations) <= device_id:
# self._configurationsappend(None)
@@ -390,6 +380,8 @@ 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
@@ -414,15 +406,15 @@ class DataServer(SocketServer, DataAPI):
c.shutdown()
c.join()
self._spi.set_wait_flag(c._device, True)
data_runtime_process = RecordingProcess('data_server', self.log_verbose, device_id,
Queue(), self._queue_ds_dict[int(device_id)], self._queue_msg, meta_file,
json_stringify(_device), _parameter, _parent, _recording_file_name,
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
project_id = project_id,
database = self.database_process)
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
database = self.database_process )
# data_runtime_process.start()
# 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)
@@ -654,7 +646,6 @@ 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
@@ -663,9 +654,6 @@ 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()
@@ -674,18 +662,15 @@ 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.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
if self._configurations[device].queue_flag:
self._configurations[device].queue_flag = False
print("q size= ", self._configurations[device]._queue_rec.qsize())
self._configurations[device].put_rec_queue(data)
# self._no_data_total_duration = 0
ret = True
# else:
# time_diff = time() - self._recv_memory_cost_time
# self._no_data_total_duration += time_diff
@@ -714,9 +699,6 @@ class DataServer(SocketServer, DataAPI):
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True)
return True
def show_data(self, device):
self._configurations[device].put_rec_queue('show_data')
class DataRuntime(metaclass=abc.ABCMeta):
__slots__ = ('_server', '_device', '_meta_file', '_data_format',
+3 -34
View File
@@ -222,8 +222,7 @@ class DataBaseProcess(Process):
try:
sql_cursor.execute(sql_str, sql_set)
except BaseException as e:
print('meta create error', e)
except:
self._psql_conn.commit()
sql_cursor.close()
self._queue_error.put(device_id)
@@ -250,8 +249,7 @@ class DataBaseProcess(Process):
try:
sql_cursor.execute(sql_str, sql_set)
except BaseException as e:
print('meta update error', e)
except:
self._psql_conn.commit()
sql_cursor.close()
self._queue_error.put(device_id)
@@ -552,33 +550,4 @@ class DataBaseProcess(Process):
except psycopg2.Error as e:
print('e', e)
return True
def project_insert(self, device_id, _data):
sql_str = 'INSERT INTO "public"."project_metas" ('
sql_set = []
for item in _data.keys():
sql_str = sql_str + str(item) + ', '
if isinstance(_data[item], dict) or isinstance(_data[item], list):
sql_set.append(json_stringify(_data[item]))
else:
sql_set.append(_data[item])
sql_str = sql_str[0:-2] + ') VALUES ('
for item in _data.keys():
sql_str = sql_str + '%s, '
sql_str = sql_str[0:-2] + ') RETURNING id'
sql_cursor = self._psql_conn.cursor()
try:
sql_cursor.execute(sql_str, sql_set)
except BaseException as e:
print('insert error', e)
self._psql_conn.commit()
sql_cursor.close()
self._queue_error.put()
finally:
self._queue_ds[int(device_id)].put(['project_id', int(sql_cursor.fetchone()[0])])
self._psql_conn.commit()
sql_cursor.close()
return True
+16 -145
View File
@@ -1,7 +1,6 @@
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
@@ -32,14 +31,8 @@ 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
from biopro.db.base import Base, Session, engine
from biopro.db.project_report import ProjectReport
from biopro.db.project_meta import MetaProjectInfo
# from biopro.db.device import Device
from biopro.db.recording_data import get_raw_model
from biopro.db.subject_data import SubjectData
from biopro.db.meta import RecordingDataMeta
import random
### do not import Websocket mode
###from .websocket import WebsocketThread
_RUNTIME_COMPILE = False
@@ -112,7 +105,7 @@ class ControlServer(SocketServer, ControlServerAPI):
# device detect
self._detect_device_thread = RoutineConnectDeviceThread(self._device_manager, self.mqtt_thread, self.led_thread, 3)
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread, self.log_verbose)
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread)
if not c.flag_disable_led_control:
self.led_thread.set_state(LED.COLOR_RED)
@@ -124,8 +117,8 @@ class ControlServer(SocketServer, ControlServerAPI):
self.ups_thread = UPSDetectThread(self, c.flag_ups_wait_time)
# user session
# self._session = {}
# self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
self._session = {}
self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
# indicate those device together
self._device_instruction_group = None
@@ -136,10 +129,6 @@ class ControlServer(SocketServer, ControlServerAPI):
# _api request build
self._api = ApiRequests()
# sqlalchemy
Base.metadata.create_all(engine)
self._session = Session()
# init method
def _init_file_manager(self, option: ControlServerOptions) -> FileManager:
@@ -332,18 +321,6 @@ class ControlServer(SocketServer, ControlServerAPI):
finally:
self.led_thread.set_state(LED.AVAILABLE)
# version_info = [0, 2, 1, 7, 23, 2]
# serial_number = DeviceSerialNumber(version_info[0],
# version_info[1],
# version_info[2],
# version_info[3],
# version_info[4],
# version_info[5])
# response = DeviceResponseInfo('Elite-EDC', serial_number, (164, 218, 50, 212, 231, 12), addr_type=0)
# print('setup done', response)
# ret = self.device_manager.connect(response)
# print('ret', ret)
def _setup_get_available_channel(self) -> Optional[List[int]]:
client = self.data_server.client()
@@ -573,15 +550,8 @@ class ControlServer(SocketServer, ControlServerAPI):
response = content
else:
response = to_device_info(content)
try:
# version_info = [0, 2, 1, 7, 23, 2]
# serial_number = DeviceSerialNumber(version_info[0],
# version_info[1],
# version_info[2],
# version_info[3],
# version_info[4],
# version_info[5])
# response = DeviceResponseInfo('Elite-EDC', serial_number, (164, 218, 50, 212, 231, 12))
ret = self.device_manager.connect(response)
except DeviceInstructionError as e:
'''when device reset fail error'''
@@ -849,21 +819,12 @@ class ControlServer(SocketServer, ControlServerAPI):
return True
@logging_info
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
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
@logging_info
def device_parent(self, device: int, content: Optional[str] = None) -> List[int]:
@@ -1055,16 +1016,6 @@ class ControlServer(SocketServer, ControlServerAPI):
def run_project(self, project) -> bool:
if project is not None:
project = self._project_manager.create(project)
with self._session as session:
project_report = ProjectReport(
name = project.name,
uuid = project.uuid,
cycle = project.cycle,
task = project.task_list,
device = project.device
)
session.add(project_report)
session.commit()
self._project_manager.run_project(project)
return project.as_json()
@@ -1073,18 +1024,6 @@ class ControlServer(SocketServer, ControlServerAPI):
if project is not None:
self._project_manager.stop_project(project)
return True
@logging_info
def set_project(self, project, content) -> bool:
if project is not None:
self._project_manager.set_project(project, content)
return True
@logging_info
def set_project_cycle(self, project, index, content) -> bool:
if project is not None:
self._project_manager.set_project_cycle(project, index, content)
return True
@logging_info
def get_running_project(self) -> bool:
@@ -1106,10 +1045,6 @@ class ControlServer(SocketServer, ControlServerAPI):
elif oper == InternalInstruction.PREDEFINED_DISABLE_CACHE:
return True
elif oper == InternalInstruction.PREDEFINED_IDLE:
device.status = 1
return True
else:
return False
@@ -1124,8 +1059,6 @@ class ControlServer(SocketServer, ControlServerAPI):
self.log_verbose('update data format', value)
client = self.data_server.client()
project = None
_project_meta_id = None
if client is not None:
info = self.file_manager.use(device)
@@ -1136,15 +1069,9 @@ class ControlServer(SocketServer, ControlServerAPI):
filename = self._file_save_cache.get(device.device_id, self.TEMP_FILENAME_EXPR)
filename = format_filename(filename, device)
info = self.file_manager.save(device, filename)
if device.occupied_by_project != None:
project = self.project_manager.get(device.occupied_by_project).info_pass_data_server()
_project_meta_id = MetaProjectInfo.create_project_meta(project)
new_project = self.project_manager.get(device.occupied_by_project)
new_project.project_meta_id = _project_meta_id
with client:
client.update_device_configuration(device, info.meta_file, value, _project_meta_id)
client.update_device_configuration(device, info.meta_file, value)
def _device_set_disable_cache(self, device: CompletedDevice, disable):
if disable:
@@ -1178,6 +1105,7 @@ class ControlServer(SocketServer, ControlServerAPI):
filename = format_filename(self.TEMP_FILENAME_EXPR, device)
info = self.file_manager.save(device, filename)
client.update_device_configuration(device, info.meta_file, RawDataDecoder())
if self._device_instruction_group is None:
client.start_sync(device)
@@ -1374,57 +1302,6 @@ class ControlServer(SocketServer, ControlServerAPI):
} for pkg in PipPackage.list()]
return ret
def save_data_to_subject(self, project, meta, device, subject):
mode = device.get_parameter('MODE')
library = device.library_name
device = {
"library": library,
"mode": mode
}
# "pattern": {
# "id": number,
# "name": string,
# "parameter": object,
# },
# "data": {
# "id": list[int],
# "channel: list[int]
# }
with Session() as session:
meta_result = session.query(RecordingDataMeta).filter(RecordingDataMeta.project == meta).first()
self.mqtt_thread.publish('', json.dumps({
"pattern": {
"id": 4,
},
"data": {
"id": [meta_result.id],
"channel": ['Time', 6]
},
"others": {
"subject": subject,
"device": device,
"project": project,
"project_meta": meta,
}
}), analysis= True)
# result = session.query(recording_raws).order_by(recording_raws.id.desc()).first()
# value = result.data.split(' ')[1:-1:2]
# _value = list(map(int, value))
# sum_value = sum(_value)
# average_value = sum_value / len(_value)
# subject_data = SubjectData(
# subject_id= subject['id'],
# project = project,
# meta = meta,
# mode= device,
# data= average_value
# )
# # Execute the update query
# session.add(subject_data)
# session.commit()
def _hardware_send_test_hardware(self, section: Optional[str] = None) -> Dict[str, Any]:
if section is not None:
@@ -1462,13 +1339,7 @@ class ControlServer(SocketServer, ControlServerAPI):
def _hardware_send_test_set(self, options: Dict[str, str]) -> bool:
# TODO write options files
return False
@logging_info
def show_device_data(self, device: int):
client = self.data_server.client()
if client is not None:
with client:
client.show_data(device)
class _RandomCrashThread(ServerThread):
def __init__(self):
super().__init__('Crash')
+1 -3
View File
@@ -170,11 +170,9 @@ class MqttThread(threading.Thread):
self.sleep(3)
self._mqtt_client_local.reconnect()
def publish(self, topic: str, payload: str, inter = False, analysis=False, qos = 2):
def publish(self, topic: str, payload: str, inter = False, qos = 2):
if inter:
_topic = self.__controller_ID + '_user'
elif analysis:
_topic = self.__controller_ID + '_data_analysis/get_analysis_data'
else:
_topic = self.__controller_ID + '/' + topic
if self._mqtt_client_local is not None:
+5 -6
View File
@@ -44,9 +44,7 @@ class RecordingProcess(Process):
def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, queue_msg, meta_path,
device_info, parameter, parent, recording_file_name, data_format,
mqtt_ip, mqtt_port,
name = 'Recording-Process',
project_id = None,
database = None):
name = 'Recording-Process', database = None):
super(RecordingProcess, self).__init__(name = name)
self._database = database
@@ -59,7 +57,6 @@ 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)
@@ -158,6 +155,9 @@ class RecordingProcess(Process):
elif isinstance(decoder, EISZeroOneDataDecoder):
# get amp_gain from meta file
decoder._mode = self._meta_file.configuration.get_parameter('MODE')
decoder._ac_amp = self._meta_file.configuration.get_parameter('AC_AMP')
decoder._freq_start = self._meta_file.configuration.get_parameter('FREQ_START')
decoder._freq_stop = self._meta_file.configuration.get_parameter('FREQ_STOP')
return decoder
@@ -185,8 +185,6 @@ 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)
@@ -236,6 +234,7 @@ class RecordingProcess(Process):
if len(self._mqtt_send_data_ch_level) == 0:
for ch in result.channels():
self._mqtt_send_data_ch_level[ch] = MqttDataMessageHandler(self._mqtt_thread, 'data_server/device_data_stream/' + str(result.device) + '/' + str(ch) )
self._mqtt_send_data_ch_level[50+ch] = MqttDataMessageHandler(self._mqtt_thread, 'data_server/device_data_stream/' + str(result.device) + '/' + str(ch+50) )
ret.append(result)
else:
continue
+5 -7
View File
@@ -93,15 +93,13 @@ class SocketClient(metaclass=abc.ABCMeta):
if self._socket is None:
try:
self._socket = Socket(AF_UNIX, SOCK_STREAM)
self._socket.settimeout(5)
self._socket.settimeout(1)
self._socket.connect(self._socket_file)
except Exception as e:
print('open_socket error:', e)
# except FileNotFoundError as e:
# raise RuntimeError('server not available') from 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:
@@ -1203,7 +1203,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X0C;",
"X07;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -1633,6 +1633,16 @@
"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')"
@@ -492,6 +492,14 @@
"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": {
@@ -15,33 +15,6 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -698,17 +671,6 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -874,18 +836,6 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -901,8 +851,7 @@
"initial": 0,
"value": [
"Iin",
"Vin",
"Vout"
"Vin"
]
},
"BLE_WRITE": {
@@ -963,13 +912,11 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin",
"2": "cali_Vout"
"1": "cali_Vin"
}
},
"_sync(True)",
@@ -1060,6 +1007,12 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1072,12 +1025,6 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1105,22 +1052,13 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -1141,7 +1079,7 @@
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"ve": "CYCLE_NUMBER",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
@@ -1265,7 +1203,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X0C;",
"X07;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -1695,6 +1633,16 @@
"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')"
@@ -15,33 +15,6 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -698,17 +671,6 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -874,18 +836,6 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -901,8 +851,7 @@
"initial": 0,
"value": [
"Iin",
"Vin",
"Vout"
"Vin"
]
},
"BLE_WRITE": {
@@ -963,13 +912,11 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin",
"2": "cali_Vout"
"1": "cali_Vin"
}
},
"_sync(True)",
@@ -1060,6 +1007,12 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1072,12 +1025,6 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1105,22 +1052,13 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -1141,7 +1079,7 @@
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"ve": "CYCLE_NUMBER",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
@@ -1265,7 +1203,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X0C;",
"X07;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -1695,6 +1633,16 @@
"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')"
@@ -15,34 +15,6 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -618,8 +590,7 @@
"Open Circuit Potential",
"Pulse Sensing",
"Differential Pulse Voltammetry (DPV)",
"Chronopotentiometry",
"Idle"
"Chronopotentiometry"
]
},
"VOLT_ORIGIN": {
@@ -700,17 +671,6 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -876,18 +836,6 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -903,8 +851,7 @@
"initial": 0,
"value": [
"Iin",
"Vin",
"Vout"
"Vin"
]
},
"BLE_WRITE": {
@@ -951,7 +898,6 @@
"10": "cali_dac_test",
"11": "cali_adc_test",
"12": "",
"17": "idle",
"*": "start_data"
}
}
@@ -966,22 +912,17 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin",
"2": "cali_Vout"
"1": "cali_Vin"
}
},
"_sync(True)",
"VIS_STI",
"_cdr('1X;4X>ADC_VALUE_I')"
],
"idle": [
"_idle()"
],
"start_data": [
"data_format",
"_notify(True)",
@@ -1066,6 +1007,12 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1078,12 +1025,6 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1111,22 +1052,13 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -1147,7 +1079,7 @@
"va": "VOLT_ORIGIN",
"vb": "VOLT_FINAL",
"vc": "VOLT_STEP",
"vd": "STEP_TIME",
"vd": "STEP_TIME * 0x12",
"ve": "CYCLE_NUMBER",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
@@ -1271,7 +1203,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X0C;",
"X07;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -1701,6 +1633,16 @@
"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')"
+167 -353
View File
@@ -9,7 +9,7 @@
"minor_version_number": 0
},
"constant": {
"FREQ_MAX": 13333334,
"FREQ_MAX": 4294967296,
"VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
@@ -26,43 +26,17 @@
"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",
"CHANNEL": {
"derzteription": "record channels",
"record_meta": true,
"initial": 1,
"value": [
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
"domain": "property",
"value": "[0, 1, 2]"
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"initial": 1,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
@@ -76,12 +50,6 @@
},
"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,
@@ -94,63 +62,14 @@
"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",
"FREQ": {
"description": "DPV current recording period start",
"record_meta": true,
"initial": [
13333333,
13422819,
7
],
"domain": {
@@ -160,24 +79,29 @@
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"FREQ_START": {
"description": "Start of Freq Scan",
"record_meta": true,
"initial": 10,
"initial": 13422819,
"domain": [
11
]
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"FREQ_STOP": {
"description": "End of Freq Scan",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
"initial": 7,
"domain": [
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_DELAY": {
"DELAY": {
"description": "Wait x peroid before start taking measurements",
"record_meta": true,
"initial": 0,
@@ -188,19 +112,19 @@
"expression": "VALUE"
}
},
"EIS_AVERAGE_NUM": {
"AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"record_meta": true,
"initial": 8,
"value": [
2,
4,
6,
8
8,
16
]
},
"CF_DC_BIAS": {
"description": "DC voltage bias",
"DC_BIAS": {
"description": "DC voltage bias in mV",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -210,34 +134,15 @@
"expression": "VALUE"
}
},
"CF_AC_AMP": {
"description": "AC Amplitude",
"AC_AMP": {
"description": "AC Amplitude in mV",
"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": {
"SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
@@ -246,29 +151,77 @@
1
]
},
"CF_DELAY": {
"description": "Wait x peroid before start taking measurements",
"PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 0,
"initial": 10,
"domain": [
101
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"
}
},
"CF_AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
"initial": 8,
"initial": 1,
"value": [
2,
4,
6,
8
]
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
},
"CV_E_INITIAL": {
"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,
@@ -279,8 +232,8 @@
"expression": "VALUE"
}
},
"CV_E1": {
"description": "First voltage of Scan",
"VOLT_MAX": {
"description": "Max Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -290,8 +243,8 @@
"expression": "VALUE"
}
},
"CV_E2": {
"description": "Second voltage of Scan",
"VOLT_MIN": {
"description": "Min Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -301,54 +254,16 @@
"expression": "VALUE"
}
},
"CV_SCAN_RATE": {
"description": "Voltage scan rate",
"CYCLE_NUMBER": {
"description": "CV cycle number",
"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,
"initial": 1,
"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",
@@ -380,38 +295,27 @@
{
"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"
"1": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3",
"2": "curve_ca",
"3": "curve_vt",
"4": "curve_rt",
"5": "curve_cf"
"1": "curve_cv3"
}
},
{
"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"
"1": "curve_cv3_para2"
}
},
"_sync(True)",
@@ -431,18 +335,6 @@
"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": {
@@ -452,172 +344,94 @@
"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": [
"1XFF;1X72;1B>CTRL_HIGH_Z_15"
"XE1;X03;B>CTRL_HIGH_Z_15"
]
},
"curve_eis": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "SCALE"
},
"data": [
"1X12;1X01;4B>fa;4B>fb;2B>dp"
"1XD1;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"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "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"
"1XD1;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_cv3": {
"type": "RIS",
"parameter": {
"va": "CV_E_INITIAL",
"vb": "CV_E1",
"vc": "CV_E2",
"ve": "CV_SCAN_RATE",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X01;2B>va;2B>vb;2B>vc;"
"1XD2;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",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_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"
"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')"
+168 -360
View File
@@ -9,7 +9,7 @@
"minor_version_number": 1
},
"constant": {
"FREQ_MAX": 13333334,
"FREQ_MAX": 4294967296,
"VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
@@ -26,44 +26,17 @@
"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",
"CHANNEL": {
"derzteription": "record channels",
"record_meta": true,
"initial": 1,
"value": [
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
"domain": "property",
"value": "[0, 1, 2]"
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"initial": 1,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
@@ -77,12 +50,6 @@
},
"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,
@@ -95,64 +62,14 @@
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"V-T Graph",
"R-T Graph",
"EIS constant frequency",
"Dev Mode",
"Idle"
"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",
"FREQ": {
"description": "DPV current recording period start",
"record_meta": true,
"initial": [
13333333,
13422819,
7
],
"domain": {
@@ -162,24 +79,29 @@
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"FREQ_START": {
"description": "Start of Freq Scan",
"record_meta": true,
"initial": 10,
"initial": 13422819,
"domain": [
11
]
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"FREQ_STOP": {
"description": "End of Freq Scan",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
"initial": 7,
"domain": [
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_DELAY": {
"DELAY": {
"description": "Wait x peroid before start taking measurements",
"record_meta": true,
"initial": 0,
@@ -190,19 +112,19 @@
"expression": "VALUE"
}
},
"EIS_AVERAGE_NUM": {
"AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"record_meta": true,
"initial": 8,
"value": [
2,
4,
6,
8
8,
16
]
},
"CF_DC_BIAS": {
"description": "DC voltage bias",
"DC_BIAS": {
"description": "DC voltage bias in mV",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -212,34 +134,15 @@
"expression": "VALUE"
}
},
"CF_AC_AMP": {
"description": "AC Amplitude",
"AC_AMP": {
"description": "AC Amplitude in mV",
"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": {
"SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
@@ -248,29 +151,77 @@
1
]
},
"CF_DELAY": {
"description": "Wait x peroid before start taking measurements",
"PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 0,
"initial": 10,
"domain": [
101
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"
}
},
"CF_AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
"initial": 8,
"initial": 1,
"value": [
2,
4,
6,
8
]
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
},
"CV_E_INITIAL": {
"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,
@@ -281,8 +232,8 @@
"expression": "VALUE"
}
},
"CV_E1": {
"description": "First voltage of Scan",
"VOLT_MAX": {
"description": "Max Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -292,8 +243,8 @@
"expression": "VALUE"
}
},
"CV_E2": {
"description": "Second voltage of Scan",
"VOLT_MIN": {
"description": "Min Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -303,54 +254,16 @@
"expression": "VALUE"
}
},
"CV_SCAN_RATE": {
"description": "Voltage scan rate",
"CYCLE_NUMBER": {
"description": "CV cycle number",
"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,
"initial": 1,
"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",
@@ -372,52 +285,37 @@
{
"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"
"1": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3",
"2": "curve_ca",
"3": "curve_vt",
"4": "curve_rt",
"5": "curve_cf"
"1": "curve_cv3"
}
},
{
"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"
"1": "curve_cv3_para2"
}
},
"_sync(True)",
@@ -437,18 +335,6 @@
"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": {
@@ -458,172 +344,94 @@
"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": [
"1XFF;1X72;1B>CTRL_HIGH_Z_15"
"XE1;X03;B>CTRL_HIGH_Z_15"
]
},
"curve_eis": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "SCALE"
},
"data": [
"1X12;1X01;4B>fa;4B>fb;2B>dp"
"1XD1;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"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "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"
"1XD1;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_cv3": {
"type": "RIS",
"parameter": {
"va": "CV_E_INITIAL",
"vb": "CV_E1",
"vc": "CV_E2",
"ve": "CV_SCAN_RATE",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X01;2B>va;2B>vb;2B>vc;"
"1XD2;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",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_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"
"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')"
@@ -9,7 +9,7 @@
"minor_version_number": 2
},
"constant": {
"FREQ_MAX": 13333334,
"FREQ_MAX": 4294967296,
"VOLT_MAX": 65536,
"BLE_WRITE_MAX": 255,
"TIME_MAX": 100000
@@ -26,44 +26,17 @@
"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",
"CHANNEL": {
"derzteription": "record channels",
"record_meta": true,
"initial": 1,
"value": [
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
"domain": "property",
"value": "[0, 1, 2]"
},
"CYCLE_NUMBER": {
"description": "CV cycle number",
"CHANNEL_LABEL": {
"description": "channel label",
"record_meta": true,
"initial": 1,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
"domain": "property",
"value": "['current', 'voltage', 'impedance']"
},
"SAMPLE_RATE": {
"description": "data sampling rate",
@@ -77,12 +50,6 @@
},
"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,
@@ -95,64 +62,14 @@
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"V-T Graph",
"R-T Graph",
"EIS constant frequency",
"Dev Mode",
"Idle"
"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",
"FREQ": {
"description": "DPV current recording period start",
"record_meta": true,
"initial": [
13333333,
13422819,
7
],
"domain": {
@@ -162,24 +79,29 @@
},
"value": "VALUE"
},
"EIS_PPD": {
"description": "Point per decades",
"FREQ_START": {
"description": "Start of Freq Scan",
"record_meta": true,
"initial": 10,
"initial": 13422819,
"domain": [
11
]
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_SCALE": {
"description": "Point spacing pattern",
"FREQ_STOP": {
"description": "End of Freq Scan",
"record_meta": true,
"initial": 0,
"value": [
0,
1
]
"initial": 7,
"domain": [
"FREQ_MAX"
],
"value": {
"expression": "VALUE"
}
},
"EIS_DELAY": {
"DELAY": {
"description": "Wait x peroid before start taking measurements",
"record_meta": true,
"initial": 0,
@@ -190,19 +112,19 @@
"expression": "VALUE"
}
},
"EIS_AVERAGE_NUM": {
"AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"record_meta": true,
"initial": 8,
"value": [
2,
4,
6,
8
8,
16
]
},
"CF_DC_BIAS": {
"description": "DC voltage bias",
"DC_BIAS": {
"description": "DC voltage bias in mV",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -212,34 +134,15 @@
"expression": "VALUE"
}
},
"CF_AC_AMP": {
"description": "AC Amplitude",
"AC_AMP": {
"description": "AC Amplitude in mV",
"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": {
"SCALE": {
"description": "Point spacing pattern",
"record_meta": true,
"initial": 0,
@@ -248,29 +151,77 @@
1
]
},
"CF_DELAY": {
"description": "Wait x peroid before start taking measurements",
"PPD": {
"description": "Point per decades",
"record_meta": true,
"initial": 0,
"initial": 10,
"domain": [
101
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"
}
},
"CF_AVERAGE_NUM": {
"description": "Number of sample used for average funciton",
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
"initial": 8,
"initial": 1,
"value": [
2,
4,
6,
8
]
"On",
"Off"
],
"on_change": "set_ctrl_highZ"
},
"CV_E_INITIAL": {
"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,
@@ -281,8 +232,8 @@
"expression": "VALUE"
}
},
"CV_E1": {
"description": "First voltage of Scan",
"VOLT_MAX": {
"description": "Max Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -292,8 +243,8 @@
"expression": "VALUE"
}
},
"CV_E2": {
"description": "Second voltage of Scan",
"VOLT_MIN": {
"description": "Min Voltage of Scan",
"record_meta": true,
"initial": 25000,
"domain": [
@@ -303,54 +254,16 @@
"expression": "VALUE"
}
},
"CV_SCAN_RATE": {
"description": "Voltage scan rate",
"CYCLE_NUMBER": {
"description": "CV cycle number",
"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,
"initial": 1,
"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",
@@ -372,52 +285,37 @@
{
"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"
"1": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3",
"2": "curve_ca",
"3": "curve_vt",
"4": "curve_rt",
"5": "curve_cf"
"1": "curve_cv3"
}
},
{
"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"
"1": "curve_cv3_para2"
}
},
"_sync(True)",
@@ -437,18 +335,6 @@
"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": {
@@ -458,172 +344,94 @@
"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": [
"1XFF;1X72;1B>CTRL_HIGH_Z_15"
"XE1;X03;B>CTRL_HIGH_Z_15"
]
},
"curve_eis": {
"type": "RIS",
"parameter": {
"fa": "EIS_FREQ[0]",
"fb": "EIS_FREQ[1]",
"dp": "EIS_DELAY",
"dc": "EIS_DC_BIAS",
"am": "EIS_AC_AMP",
"an": "EIS_AVERAGE_NUM",
"rt": "GENERAL_HS_RTIA",
"pp": "EIS_PPD",
"sp": "EIS_SCALE"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "SCALE"
},
"data": [
"1X12;1X01;4B>fa;4B>fb;2B>dp"
"1XD1;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"
"fa": "FREQ[0]",
"fb": "FREQ[1]",
"dp": "DELAY",
"dc": "DC_BIAS",
"am": "AC_AMP",
"an": "AVERAGE_NUM",
"rt": "RTIA",
"pp": "PPD",
"sp": "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"
"1XD1;1X02;2B>dc;2B>am;B>an;B>rt;2B>pp;B>sp"
]
},
"curve_cv3": {
"type": "RIS",
"parameter": {
"va": "CV_E_INITIAL",
"vb": "CV_E1",
"vc": "CV_E2",
"ve": "CV_SCAN_RATE",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X01;2B>va;2B>vb;2B>vc;"
"1XD2;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",
"va": "VOLT_INITIAL",
"vb": "VOLT_MAX",
"vc": "VOLT_MIN",
"ve": "Scan_Rate",
"vf": "SAMPLE_RATE",
"cn": "CYCLE_NUMBER"
},
"data": [
"1X09;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_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"
"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')"
@@ -1426,6 +1426,14 @@
"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",
@@ -9,20 +9,9 @@
"minor_version_number": 0
},
"constant": {
"TIME_MAX": 100000
},
"parameters": {
"TIME_DURATION": {
"description": "timer",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"ACC_a_out0": {
"description": "Switch of analog current channel 1",
"record_meta": true,
-32
View File
@@ -1,32 +0,0 @@
#!/bin/bash
# install python module numpy
sudo apt-get install libatlas-base-dev
sudo apt-get install python3-numpy
# install python module SQLAlchemy
pip3 install SQLAlchemy
# create folder to save project logger
mkdir -p /home/pi/logger/project
# add column cycle in projects
sudo su -c "psql -d postgres -c \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS cycle JSONB;\"" postgres
# add column project in recording_data_metas
sudo su -c "psql -d postgres -c \"ALTER TABLE recording_data_metas ADD COLUMN IF NOT EXISTS project Int4;\"" postgres
# remove default controller info
sudo su -c "psql -d postgres -c \"DELETE FROM controllers WHERE name='WTP_NONE';\"" postgres
# change table name from meta_project_info to project_metas
sudo su -c "psql -d postgres -c \"ALTER TABLE IF EXISTS meta_project_info RENAME TO project_metas;\"" postgres
# change table name from project_report to project_reports
sudo su -c "psql -d postgres -c \"ALTER TABLE IF EXISTS project_report RENAME TO project_reports;\"" postgres
# change table project_meta column cycle to type jsonb
sudo su -c "psql -d postgres -c \"ALTER TABLE project_metas ALTER COLUMN cycle type jsonb USING (cycle::jsonb);\"" postgres
# add column subject in project
sudo su -c "psql -d postgres -c \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS subject JSONB;\"" postgres