Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5531dcc0f0 | |||
| c0bb567bf7 | |||
| 58e09bfcda | |||
| 55780514b9 | |||
| 936514871f | |||
| f25d9221c6 | |||
| 2ee9fa6b19 | |||
| e2f7bba961 | |||
| bff75dc49e | |||
| 35912f614e | |||
| cfc4e39c8a | |||
| 8c4916d1e8 | |||
| e3c252f204 | |||
| c2164da48b | |||
| ab2d746afb | |||
| 8a870a860a | |||
| f4c5cf0135 | |||
| 1f01fd3b9b | |||
| d1fe388c27 | |||
| 91d5e73c5e | |||
| d1b6c2892f | |||
| 4243a13536 | |||
| 97188abff8 | |||
| 9d8178d11a | |||
| bbde653a8e | |||
| 6c0cef7925 | |||
| 3bbf0c912a | |||
| 4333958ebe | |||
| 3239a691e3 | |||
| 30183788d8 | |||
| 13df921b1c | |||
| d182a04ed3 | |||
| 35a09ff9a0 | |||
| e134b9780c | |||
| df39f241b3 | |||
| 0b72ac0c9d | |||
| 0afbe66229 | |||
| 9846cfd708 | |||
| b4ad2a7fba | |||
| 675fdc2226 | |||
| a847b1222d | |||
| bd0c36923a | |||
| 612785f51a | |||
| 7dbf09e9a5 | |||
| ee64d43de1 | |||
| 60b91f0c1e | |||
| 8ac01bdf54 | |||
| 0f90b16b6e | |||
| cd98a14e84 | |||
| 2e97ad23eb | |||
| e0dd5a6972 | |||
| 76e0a150d1 | |||
| ecd4b9325d | |||
| 978b1254f0 | |||
| 26e02f2d40 | |||
| 257958768f |
@@ -1585,6 +1585,15 @@ class ControlAPI(metaclass=Router):
|
||||
|
||||
def stop_project(self, project) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_project(self, project, content) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def set_project_cycle(self, project, index, content) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
def show_device_data(self, device) -> bool:
|
||||
raise NotImplementedError()
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)):
|
||||
|
||||
+16
-3
@@ -87,7 +87,8 @@ class DataAPI(metaclass=abc.ABCMeta):
|
||||
def update_device_configuration(self,
|
||||
device: Union[int, Device],
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
"""set device configuration.
|
||||
|
||||
:param device: device ID
|
||||
@@ -130,6 +131,14 @@ class DataAPI(metaclass=abc.ABCMeta):
|
||||
def hardware_test(self) -> JSON_OBJECT:
|
||||
""""""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def show_data(self, device: Union[int, Device]):
|
||||
"""show device data
|
||||
|
||||
:param device: device ID
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# noinspection PyAbstractClass
|
||||
@@ -146,7 +155,8 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
def update_device_configuration(self,
|
||||
device: Union[int, Device],
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
|
||||
# meta file
|
||||
if isinstance(meta_file, str):
|
||||
@@ -178,7 +188,7 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
raise TypeError('not a data decode format : ' + data_format.__class__.__name__)
|
||||
|
||||
# send
|
||||
self.send_command('update_device_configuration', device, meta_file, data_format)
|
||||
self.send_command('update_device_configuration', device, meta_file, data_format, project_info)
|
||||
|
||||
def is_sync(self, device: Union[None, int, Device] = None) -> bool:
|
||||
if isinstance(device, Device):
|
||||
@@ -191,6 +201,9 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
|
||||
|
||||
def stop_sync(self, *device: Union[int, Device]):
|
||||
self.send_command('stop_sync', *self._to_device_id(*device))
|
||||
|
||||
def show_data(self, device: int):
|
||||
self.send_command('show_data', device)
|
||||
|
||||
@staticmethod
|
||||
def _to_device_id(*device: Union[int, Device]) -> Tuple[int, ...]:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
from sqlalchemy import create_engine
|
||||
# from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker, declarative_base
|
||||
|
||||
SQLALCHEMY_DATABASE_URL = "postgresql://biopro:BioProControlBox@127.0.0.1:5432/postgres"
|
||||
|
||||
engine = create_engine(SQLALCHEMY_DATABASE_URL)
|
||||
Session = sessionmaker(bind=engine)
|
||||
|
||||
Base = declarative_base()
|
||||
@@ -0,0 +1,21 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base
|
||||
|
||||
class MetaProjectInfo(Base):
|
||||
__tablename__ = "meta_project_info"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
project = Column(String(36))
|
||||
cycle = Column(String)
|
||||
task = Column(JSONB)
|
||||
serial_number = Column(Integer)
|
||||
deleted = Column(Boolean, default = False)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -0,0 +1,24 @@
|
||||
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
|
||||
from sqlalchemy.sql import select, func
|
||||
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
|
||||
from .base import Base
|
||||
|
||||
class ProjectReport(Base):
|
||||
__tablename__ = "project_report"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String)
|
||||
desc = Column(String)
|
||||
task = Column(JSONB)
|
||||
cycle = Column(JSONB)
|
||||
device = Column(JSONB)
|
||||
uuid = Column(String(36))
|
||||
user_auth = Column(JSONB)
|
||||
deleted = Column(Boolean, default = False)
|
||||
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
|
||||
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
|
||||
@@ -662,7 +662,7 @@ class CC2650Device(Device):
|
||||
elif device_type == 'EISZeroOne':
|
||||
i = 0
|
||||
request_times = 0
|
||||
while i < 7:
|
||||
while i < 13:
|
||||
try:
|
||||
# send
|
||||
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
|
||||
|
||||
@@ -574,20 +574,23 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
:param device: device ID or response info
|
||||
:return: CompletedDevice, None if not found.
|
||||
"""
|
||||
if isinstance(device, int):
|
||||
for slave in self._device:
|
||||
if slave.device_id == device:
|
||||
return slave
|
||||
try:
|
||||
if isinstance(device, int):
|
||||
for slave in self._device:
|
||||
if slave.device_id == device:
|
||||
return slave
|
||||
|
||||
elif isinstance(device, str):
|
||||
for slave in self._device:
|
||||
if ':'.join('{:02x}'.format(b) for b in slave.mac_address) == device.lower():
|
||||
return slave
|
||||
elif isinstance(device, str):
|
||||
for slave in self._device:
|
||||
if ':'.join('{:02x}'.format(b) for b in slave.mac_address) == device.lower():
|
||||
return slave
|
||||
|
||||
elif isinstance(device, DeviceInfo):
|
||||
for slave in self._device:
|
||||
if device.match(slave):
|
||||
return slave
|
||||
elif isinstance(device, DeviceInfo):
|
||||
for slave in self._device:
|
||||
if device.match(slave):
|
||||
return slave
|
||||
except BaseException as e:
|
||||
self.log_error('device not found', str(device))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
+143
-70
@@ -1,6 +1,7 @@
|
||||
import abc
|
||||
import struct
|
||||
import math
|
||||
import numpy
|
||||
from typing import Optional, TypeVar, Generic, Tuple, Dict, List, AnyStr
|
||||
from datetime import datetime
|
||||
|
||||
@@ -853,7 +854,7 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
|
||||
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
|
||||
'_total_time_stamp', '_mode', '_cycle_start_time',
|
||||
'_mode_stop')
|
||||
'_mode_stop', '_show_data')
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -868,6 +869,8 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
self._mode = 0
|
||||
self._cycle_start_time = []
|
||||
|
||||
self._show_data = False
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.NAME
|
||||
@@ -892,6 +895,10 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
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]
|
||||
@@ -915,9 +922,11 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
print("error timeStamp full data:", list(data), datetime.now(), '\n')
|
||||
return None
|
||||
else:
|
||||
# print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
|
||||
# '|', current, '|', voltage, '|', impedance,
|
||||
# '|', cycle_number, '|', finishMode, '@', str(self.device))
|
||||
if self._show_data:
|
||||
print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
|
||||
'|', current, '|', voltage, '|', impedance, '|', cycle_number,
|
||||
'|', notify_one, '|', notify_two, '|', notify_three,
|
||||
'|', finishMode, '@', str(self.device))
|
||||
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:4}'.format(delta),
|
||||
@@ -946,6 +955,9 @@ 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)
|
||||
@@ -1335,7 +1347,7 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
'_total_time_stamp', '_mode', '_cycle_start_time',
|
||||
'_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff',
|
||||
'cali_coeff', '_ac_amp', '_mode', '_freq_start', '_freq_stop',
|
||||
'_freq_direction', '_last_phase', '_first_phase_flag')
|
||||
'_freq_direction', '_last_phase', '_first_phase_flag', '_show_data')
|
||||
|
||||
def __init__(self, cali_coeff: bytes = None):
|
||||
super().__init__()
|
||||
@@ -1359,6 +1371,8 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
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)
|
||||
@@ -1367,12 +1381,27 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]:
|
||||
if cali_coeff != b'':
|
||||
cali_table = []
|
||||
phase_para_a = []
|
||||
phase_para_b = []
|
||||
hsrtia_a = []
|
||||
hsrtia_b = []
|
||||
hsrtia_c = []
|
||||
hsrtia_d = []
|
||||
phase_coeff = []
|
||||
phase_offset = []
|
||||
|
||||
# phase_coeff = [[0]*4 for i in range(4)]
|
||||
# phase_offset = [[0]*4 for i in range(4)]
|
||||
|
||||
phase_coeff = numpy.zeros([4, 4], dtype = int)
|
||||
phase_offset = numpy.zeros([4, 4], dtype = int)
|
||||
|
||||
########################################
|
||||
# phase_coeff
|
||||
# [[gain0, g1, g2, g3] ----->最高頻
|
||||
# [gain0, g1, g2, g3] ----->中頻
|
||||
# [gain0, g1, g2, g3] ----->低頻
|
||||
# [gain0, g1, g2, g3] ----->最低頻
|
||||
# ]
|
||||
#######################################
|
||||
|
||||
# print('cali_coeff', cali_coeff)
|
||||
cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4
|
||||
@@ -1383,15 +1412,19 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
|
||||
|
||||
index = 20
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
|
||||
g = 0
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 40
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
|
||||
g = 0
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
#Lv[0] 160k
|
||||
index = 60
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
@@ -1416,18 +1449,58 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
|
||||
# hsrtia_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)
|
||||
index = 140
|
||||
g = 1
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 160
|
||||
g = 1
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 180
|
||||
g = 2
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 200
|
||||
g = 2
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 220
|
||||
g = 3
|
||||
phase_coeff[0][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[0][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[1][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[1][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
index = 240
|
||||
g = 3
|
||||
phase_coeff[2][g] = struct.unpack('>i', cali_coeff[index+1:index+5])[0]
|
||||
phase_offset[2][g] = struct.unpack('>i', cali_coeff[index+5:index+9])[0]
|
||||
phase_coeff[3][g] = struct.unpack('>i', cali_coeff[index+9:index+13])[0]
|
||||
phase_offset[3][g] = struct.unpack('>i', cali_coeff[index+13:index+17])[0]
|
||||
|
||||
# print('cutoff_freq', cutoff_freq)
|
||||
# print('hsrtia_a', hsrtia_a)
|
||||
# print('hsrtia_b', hsrtia_b)
|
||||
# print('hsrtia_c', hsrtia_c)
|
||||
# print('phase_para_a', phase_para_a)
|
||||
# print('phase_para_b', phase_para_b)
|
||||
# print('phase_coeff')
|
||||
# print(phase_coeff)
|
||||
# print('phase_offset')
|
||||
# print(phase_offset)
|
||||
|
||||
cali_table.append((cutoff_freq, phase_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
|
||||
cali_table.append((cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
|
||||
|
||||
return cali_table
|
||||
else:
|
||||
@@ -1477,13 +1550,12 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
return None
|
||||
else:
|
||||
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_para_a, phase_para_b, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
|
||||
cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
|
||||
|
||||
voltage_amp = round(self._ac_amp * 800 / 2047) # use UI value
|
||||
if (self._freq_start > self._freq_stop):
|
||||
self._freq_direction = 0
|
||||
@@ -1494,6 +1566,7 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
img = ch1
|
||||
real = ch2
|
||||
freq = ch3
|
||||
fre_idx = 0
|
||||
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2)
|
||||
|
||||
@@ -1513,64 +1586,64 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
else:
|
||||
impedance = 0
|
||||
|
||||
if (real > 0):
|
||||
raw_phase = math.atan(img / real) * 180 / math.pi
|
||||
elif (real == 0):
|
||||
raw_phase = 90
|
||||
else:
|
||||
raw_phase = math.atan(img / real) * 180 / math.pi + 180
|
||||
raw_phase = math.atan2(img , real) * 180 / math.pi
|
||||
|
||||
if (freq >= 1000000): # 10000 Hz
|
||||
i = 0
|
||||
fre_idx = 0
|
||||
elif (freq >= 10000): # 100 Hz
|
||||
i = 1
|
||||
fre_idx = 1
|
||||
elif (freq >= 1000): # 10 Hz
|
||||
i = 2
|
||||
fre_idx = 2
|
||||
elif (freq >= 1): # 0.01 Hz
|
||||
i = 3
|
||||
fre_idx = 3
|
||||
|
||||
ideal_raw_phase = phase_para_a[i] /1e10 * freq + phase_para_b[i] / 1e6
|
||||
|
||||
ideal_raw_phase = phase_coeff[gain][fre_idx] /1e10 * freq + phase_offset[gain][fre_idx] / 1e6
|
||||
phase = raw_phase - ideal_raw_phase
|
||||
phase = phase % 180 if phase % 180<=90 else phase % 180-180
|
||||
|
||||
if (self._first_phase_flag):
|
||||
self._last_phase = phase
|
||||
self._first_phase_flag = 0
|
||||
elif (abs(phase - self._last_phase) >= 200):
|
||||
phase -= 360
|
||||
self._last_phase = phase
|
||||
# last_phase_to90 = self._last_phase % 180 if self._last_phase % 180<=90 else self._last_phase % 180-180
|
||||
# diff = phase - last_phase_to90
|
||||
|
||||
# if (self._first_phase_flag):
|
||||
# # self._last_phase = phase
|
||||
# self._first_phase_flag = 0
|
||||
# elif (abs(diff) >= 90):
|
||||
# phase = self._last_phase + diff + (180 if diff<0 else-180)
|
||||
# else:
|
||||
# phase = self._last_phase + diff
|
||||
# self._last_phase = phase
|
||||
|
||||
imag_after_cal = impedance * math.sin(round(phase) * math.pi / 180)
|
||||
real_after_cal = impedance * math.cos(round(phase) * math.pi / 180)
|
||||
|
||||
|
||||
if (self._mode == 0):
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:5}'.format(delta),
|
||||
# '|', '{:6}'.format(ch1),
|
||||
# '|', '{:6}'.format(ch2),
|
||||
# '|', '{:8}'.format(ch3 / 100),
|
||||
# '|', '{:6}'.format(round(voltage_mag)),
|
||||
# '|', '{:5}'.format(int(imag_after_cal)),
|
||||
# '|', '{:5}'.format(int(real_after_cal)),
|
||||
# '|', '{:5}'.format(round(impedance)),
|
||||
# '|', '{:5}'.format(round(phase, 1)),
|
||||
# '|', '{:5}'.format(round(current, 3)),
|
||||
# '|', '{:1}'.format(gain),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|')
|
||||
pass
|
||||
else:
|
||||
# print('|', '{:10}'.format(time_stamp),
|
||||
# '|', '{:5}'.format(delta),
|
||||
# '|', '{:5}'.format(ch1),
|
||||
# '|', '{:5}'.format(ch2),
|
||||
# '|', '{:5}'.format(ch3),
|
||||
# '|', '{:5}'.format(cycle_number),
|
||||
# '|', '{:1}'.format(gain),
|
||||
# '|', '{:1}'.format(finishMode),
|
||||
# '@', str(self.device), '|')
|
||||
pass
|
||||
if self._show_data:
|
||||
if (self._mode == 0):
|
||||
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())
|
||||
|
||||
@@ -738,7 +738,7 @@ class DeviceCommonInstruction:
|
||||
elif instruction == cls.START:
|
||||
return '_data_format("TDC4VAF2")', '_notify(True)', 'VIS_STI', '_sync(True)'
|
||||
elif instruction == cls.INTERRUPT:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
return '_notify(False)', 'VIS_INT', '_sync(False)'
|
||||
elif instruction == cls.CLOSE:
|
||||
return '_sync(False)', '_notify(False)', 'VIS_INT'
|
||||
elif instruction == cls.CALL:
|
||||
|
||||
@@ -968,7 +968,7 @@ class CompletedDevice(Device):
|
||||
"""
|
||||
__slots__ = ('_master', '_device_id', '_device', '_library', '_context',
|
||||
'_parameter', '_configuration', '_lock', '_feature_mask',
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status')
|
||||
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project')
|
||||
|
||||
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
|
||||
"""
|
||||
@@ -986,6 +986,8 @@ class CompletedDevice(Device):
|
||||
|
||||
# device status ( 0: idle, 1: working, 2: error, 3: power off)
|
||||
self._status = 0
|
||||
# device be occupied by project
|
||||
self._occupied_by_project = None
|
||||
|
||||
# context
|
||||
s1 = library.constant
|
||||
@@ -1032,7 +1034,7 @@ class CompletedDevice(Device):
|
||||
|
||||
@property
|
||||
def mac_address_in_str(self) -> str:
|
||||
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address)
|
||||
return ':'.join('{:02x}'.format(b) for b in self._device.mac_address).upper()
|
||||
|
||||
@property
|
||||
def device(self) -> Device:
|
||||
@@ -1082,6 +1084,14 @@ class CompletedDevice(Device):
|
||||
def status(self, new_status):
|
||||
self._status = new_status
|
||||
|
||||
@property
|
||||
def occupied_by_project(self) -> str:
|
||||
return self._occupied_by_project
|
||||
|
||||
@occupied_by_project.setter
|
||||
def occupied_by_project(self, new_occupied_by_project):
|
||||
self._occupied_by_project = new_occupied_by_project
|
||||
|
||||
# device parameter getter/setter
|
||||
|
||||
def parameters(self) -> List[str]:
|
||||
@@ -1105,6 +1115,8 @@ class CompletedDevice(Device):
|
||||
return self._configuration.get_parameter(name, False)
|
||||
|
||||
def set_multi_parameters(self, parameter):
|
||||
if len(parameter) == 0:
|
||||
return
|
||||
for (name, value) in parameter[0].items():
|
||||
if name != 'target':
|
||||
self.set_parameter(name, value)
|
||||
@@ -1128,6 +1140,11 @@ class CompletedDevice(Device):
|
||||
self._parameter.set_parameter(name, value)
|
||||
# raise RuntimeError('illegal parameter value : ' + value) from e
|
||||
else:
|
||||
if name == 'MODE':
|
||||
if self.library_name.startswith('Elite_EDC'):
|
||||
self.set_parameter('CTRL_HIGH_Z_15', self.get_parameter('HIGHZ_TABLE')[value])
|
||||
self.set_parameter('TIME_DURATION', 0)
|
||||
|
||||
self._parameter.set_parameter(name, value)
|
||||
|
||||
on_change = info.on_change
|
||||
@@ -1296,6 +1313,7 @@ class CompletedDevice(Device):
|
||||
'recording_file_name': self.recording_file_name,
|
||||
'library_name': self._library.name,
|
||||
'library_version': str(self._library.version),
|
||||
'occupied_by_project': self._occupied_by_project,
|
||||
'configuration': self.configuration.as_json(list_hide=True),
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
'_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value',
|
||||
'_read_green_times','_read_red_times',
|
||||
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
|
||||
'_head_wrong_cnt')
|
||||
'_head_wrong_cnt', '_pin_busy_value')
|
||||
|
||||
def __init__(self,
|
||||
select: Selector,
|
||||
@@ -50,11 +50,11 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
||||
|
||||
# buffer
|
||||
self._tx_buffer_header = [0] * 19
|
||||
self._tx_buffer_header = [0] * 64
|
||||
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
|
||||
|
||||
# memory control pin
|
||||
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True)
|
||||
self.pin_busy: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_BZY)
|
||||
self.pin_mem_req = OutputPin.get_used(P3Pin.MEM_REQ, False)
|
||||
self.pin_mem_sel = OutputPin.get_used(P3Pin.MEM_RST, True) # MEM_RST -> actually which memory board is assign
|
||||
self.pin_ram_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL) # MEM_SEL -> actually is RAM_SEL, which RAM is assign
|
||||
@@ -62,6 +62,7 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._pin_ram_sel_value = [bool(self.pin_ram_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_sel_value = [bool(self.pin_mem_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_req_value = [bool(self.pin_mem_req) for _ in range(Selector.SIZE)]
|
||||
self._pin_busy_value = [bool(self.pin_busy) for _ in range(Selector.SIZE)]
|
||||
|
||||
self._read_green_times = 0
|
||||
self._read_red_times = 0
|
||||
@@ -98,6 +99,14 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
self._pin_ram_sel_value[channel] = True
|
||||
return self._pin_ram_sel_value[channel]
|
||||
|
||||
def get_pin_busy(self):
|
||||
channel = self.select
|
||||
if self.pin_busy.input() == 0:
|
||||
self._pin_busy_value[channel] = False
|
||||
else:
|
||||
self._pin_busy_value[channel] = True
|
||||
return self._pin_busy_value[channel]
|
||||
|
||||
@property
|
||||
def select(self) -> int:
|
||||
return self._selector.channel
|
||||
@@ -216,7 +225,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
return
|
||||
|
||||
def recv_memory(self, device: int) -> Optional[bytes]:
|
||||
self.pin_busy.output(False)
|
||||
# self.pin_busy.output(False)
|
||||
|
||||
# print('mem_req==ram_sel,[', self._pin_mem_req_value[device], ',', self._pin_ram_sel_value[device], ']')
|
||||
|
||||
rx = []
|
||||
|
||||
@@ -300,6 +311,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
print("green data print:", data, device, datetime.now())
|
||||
return None
|
||||
|
||||
# print('data=', list(data))
|
||||
# print('Ram:', data[62])
|
||||
|
||||
if (length >= 4000):
|
||||
flag_print = True
|
||||
print("green data: big length:", length)
|
||||
@@ -415,9 +429,9 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
|
||||
finally:
|
||||
# print("\n")
|
||||
self.pin_busy.output(True)
|
||||
# finally:
|
||||
# # print("\n")
|
||||
# self.pin_busy.output(True)
|
||||
|
||||
return bytes(rx)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
|
||||
self._serial = serial.Serial(self._port,
|
||||
baudrate=self._baudrate,
|
||||
timeout=0,
|
||||
writeTimeout=0.01)
|
||||
writeTimeout=1)
|
||||
# deprecate function name which change at version 3.0
|
||||
self._serial.flushInput()
|
||||
self._serial.flushOutput()
|
||||
|
||||
@@ -24,3 +24,11 @@ class Action():
|
||||
@property
|
||||
def condition(self):
|
||||
return self._condition
|
||||
|
||||
def as_json(self):
|
||||
return {
|
||||
'id': self._id,
|
||||
'type': self._type,
|
||||
'target': self._target,
|
||||
'condition': self._condition
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ class Condition():
|
||||
# print(operator, x, y)
|
||||
cases = {
|
||||
"equal": lambda a, b: a == b,
|
||||
"bigger": lambda a, b: a > b,
|
||||
"smaller": lambda a, b: a < b,
|
||||
"bigger": lambda a, b: a >= b,
|
||||
"smaller": lambda a, b: a <= b,
|
||||
}
|
||||
|
||||
return cases[operator](x, y)
|
||||
@@ -56,7 +56,8 @@ class Condition():
|
||||
return getattr(self, self.type)(**kwargs)
|
||||
|
||||
def absolute_time(self, **kwargs):
|
||||
now = int(time())
|
||||
# now = int(time())
|
||||
now = round(time(), 1)
|
||||
time_condition = round(self.datetime_to_timestamp(self.str_to_datetime(self._value)))
|
||||
|
||||
return self.compareWith(self.comparsion, now, time_condition)
|
||||
@@ -65,32 +66,80 @@ class Condition():
|
||||
project_start_time = kwargs['project_start_time']
|
||||
delay_time = kwargs['delay_time']
|
||||
|
||||
time_diff = int(time() - project_start_time - delay_time)
|
||||
return self.compareWith(self.comparsion, time_diff, int(self._value))
|
||||
# time_diff = int(time() - project_start_time - delay_time)
|
||||
time_diff = round(time() - project_start_time - delay_time, 1)
|
||||
return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
|
||||
|
||||
def after_task_run(self, **kwargs):
|
||||
# print('relative_time_from_task', kwargs,kwargs['task_start_time'],kwargs['delay_time'])
|
||||
# print('relative_time_from_task', kwargs['task_start_time'],kwargs['delay_time'])
|
||||
if len(kwargs['task_start_time']) == 0:
|
||||
return False
|
||||
task = kwargs['self_task']
|
||||
running_task = kwargs['running_task']
|
||||
task_start_time = kwargs['task_start_time'][-1]
|
||||
delay_time = kwargs['delay_time']
|
||||
|
||||
time_diff = int(time() - task_start_time - delay_time)
|
||||
# print('time_diff', time_diff)
|
||||
return self.compareWith(self.comparsion, time_diff, int(self._value))
|
||||
|
||||
time_diff = round(time() - task_start_time - delay_time, 1)
|
||||
# print('real_diff', time() - task_start_time - delay_time)
|
||||
# print(task.name, task.uuid, time_diff, round(int(self._value), 1), running_task.name, running_task.uuid)
|
||||
# if round(int(self._value), 1) == 0 and time_diff == 0.1:
|
||||
# return True
|
||||
if task.uuid != running_task.uuid:
|
||||
return False
|
||||
return self.compareWith('bigger', time_diff, round(int(self._value), 1))
|
||||
# return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
|
||||
|
||||
def device(self, **kwargs):
|
||||
print('device')
|
||||
|
||||
def previous_task_done(self, **kwargs):
|
||||
""" def previous_task_done(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
if running_task.status == 2 and self._active == False:
|
||||
self._active = True
|
||||
return True
|
||||
return False """
|
||||
|
||||
def previous_task_done(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
self_task = kwargs['self_task']
|
||||
# if running_task != None and self_task != None:
|
||||
# print('\nprevious_task_done: ', running_task.status, ' ', self._active)
|
||||
if running_task != self_task:
|
||||
if running_task == None:
|
||||
return True
|
||||
if running_task.status == 2 and self._active == False:
|
||||
# self._active = True
|
||||
return True
|
||||
return False
|
||||
|
||||
def until_button_trigger(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
if running_task != None:
|
||||
if running_task.button_trigger == True:
|
||||
running_task.button_trigger = False
|
||||
return True
|
||||
return False
|
||||
|
||||
""" def cycle(self, **kwargs):
|
||||
running_task = kwargs['running_task']
|
||||
self_task = kwargs['self_task']
|
||||
if running_task != self_task:
|
||||
if running_task.status == 2 and self._active == False:
|
||||
# self._active = True
|
||||
return True
|
||||
return False """
|
||||
|
||||
def str_to_datetime(self, time_str):
|
||||
return datetime.strptime(time_str,'%Y-%m-%dT%H:%M')
|
||||
|
||||
def datetime_to_timestamp(self, date):
|
||||
return datetime.timestamp(date)
|
||||
return datetime.timestamp(date)
|
||||
|
||||
def as_json(self):
|
||||
return {
|
||||
'id': self._id,
|
||||
'type': self._type,
|
||||
'comparsion': self._comparsion,
|
||||
'value': self._value,
|
||||
'active': self._active
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ class Instruction():
|
||||
|
||||
self._start_instruction = list(map(lambda ins: self._instruction_set[ins] ,['set_file_name', 'set_parent', 'set_parameter', 'call_instruction']))
|
||||
self._stop_instruction = list(map(lambda ins: self._instruction_set[ins] ,['call_instruction']))
|
||||
self._idle_instruction = []
|
||||
|
||||
@property
|
||||
def start(self) -> list:
|
||||
@@ -29,4 +30,8 @@ class Instruction():
|
||||
|
||||
@property
|
||||
def stop(self) -> list:
|
||||
return self._stop_instruction
|
||||
return self._stop_instruction
|
||||
|
||||
@property
|
||||
def idle(self) -> list:
|
||||
return self.idle_instruction
|
||||
@@ -19,12 +19,12 @@ key_list = {
|
||||
}
|
||||
|
||||
class Project(threading.Thread):
|
||||
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, name="project"):
|
||||
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, log_verbose = None, name="project"):
|
||||
super(Project, self).__init__(name = name)
|
||||
self._project = project
|
||||
self._device_manager = device_manager
|
||||
self._mqtt_thread = mqttThread
|
||||
self._time_interval = 1
|
||||
self._time_interval = 0.1
|
||||
self._start_time = None
|
||||
self._end_time = None
|
||||
|
||||
@@ -33,7 +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()
|
||||
@@ -41,6 +41,12 @@ class Project(threading.Thread):
|
||||
|
||||
self._task_manager = None
|
||||
|
||||
self._cycle = []
|
||||
|
||||
self._count = 1 #流水號
|
||||
|
||||
self.log_verbose = log_verbose
|
||||
|
||||
self.setup_project(project)
|
||||
self.setup_device(self._device)
|
||||
|
||||
@@ -50,7 +56,7 @@ class Project(threading.Thread):
|
||||
key = key_list[key]
|
||||
|
||||
if key == 'task':
|
||||
self._task_manager = TaskManager(project['task'])
|
||||
self._task_manager = TaskManager(project['task'], project['cycle'])
|
||||
elif key == 'uuid':
|
||||
pass
|
||||
else:
|
||||
@@ -58,8 +64,10 @@ class Project(threading.Thread):
|
||||
|
||||
def setup_device(self, device_list):
|
||||
for device in device_list:
|
||||
complete_device = self._device_manager.get_device(device['connectDevice']['device_address'])
|
||||
self._complete_device.append(complete_device)
|
||||
mac_address = device_list[device]['pair']
|
||||
complete_device = self._device_manager.get_device(mac_address)
|
||||
complete_device.occupied_by_project = self._uuid
|
||||
self._complete_device[device] = complete_device
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
@@ -84,6 +92,14 @@ class Project(threading.Thread):
|
||||
@name.setter
|
||||
def name(self, new_name):
|
||||
self._name = new_name
|
||||
|
||||
@property
|
||||
def cycle(self) -> list:
|
||||
return self._cycle
|
||||
|
||||
@cycle.setter
|
||||
def cycle(self, new_cycle):
|
||||
self._cycle = new_cycle
|
||||
|
||||
@property
|
||||
def desc(self) -> str:
|
||||
@@ -117,9 +133,14 @@ class Project(threading.Thread):
|
||||
def mqtt_thread(self):
|
||||
return self._mqtt_thread
|
||||
|
||||
@property
|
||||
def running_task(self):
|
||||
return self._task_manager.running_task
|
||||
|
||||
def run(self):
|
||||
self._status = 1
|
||||
self._start_time = time()
|
||||
self.log_verbose('Project ' + self.name + ' start')
|
||||
self.mqtt_thread.broadcast_command('project:' + self._name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
|
||||
while not self._stop_flag :
|
||||
@@ -130,41 +151,94 @@ class Project(threading.Thread):
|
||||
for task in check_list:
|
||||
if task != None:
|
||||
now = time()
|
||||
# print('round task', task.name)
|
||||
# print('running task', self._task_manager.running_task.name, self._task_manager.running_task.status)
|
||||
# if self._task_manager.prev_task != None:
|
||||
# print('previous_task', self._task_manager.prev_task.name, self._task_manager.prev_task.status)
|
||||
|
||||
match_condition_list = task.check_condition(
|
||||
project_start_time = self._start_time,
|
||||
delay_time = delay_time,
|
||||
running_task= self._task_manager.running_task,
|
||||
previous_task = self._task_manager.prev_task
|
||||
previous_task = self._task_manager.prev_task,
|
||||
self_task = task
|
||||
)
|
||||
# print('match_condition_list', match_condition_list)
|
||||
|
||||
for condition in match_condition_list:
|
||||
match_action_list = task.get_match_action(condition.id)
|
||||
for action in match_action_list:
|
||||
# print('match_action', action.type, action.target)
|
||||
if action.type == 'start' and task.status != 1:
|
||||
self._task_manager.set_running_task(task)
|
||||
if action.type == 'cycle' and condition.type == 'previous_task_done':
|
||||
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
self._task_manager.set_running_task(task)
|
||||
if action.type == 'cycle' and condition.type == 'until_button_trigger':
|
||||
self._task_manager.running_task.stop()
|
||||
|
||||
device = self._complete_device[action.target]
|
||||
task_info = task.get_task_info(action)
|
||||
instruction_set = getattr(self._instruction_set, action.type, None)
|
||||
# print('instruction_set',instruction_set)
|
||||
|
||||
if instruction_set != None:
|
||||
for instruction in instruction_set:
|
||||
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
|
||||
threading.Thread(target=getattr(device, instruction['method'])(*args))
|
||||
if self._task_manager.running_task != None:
|
||||
if self._task_manager.running_task.uuid == task.uuid and action.type == 'cycle' and condition.type == 'after_task_run':
|
||||
self._task_manager.running_task.stop()
|
||||
|
||||
if action.type == 'start':
|
||||
if task.status != 1:
|
||||
self._task_manager.set_running_task(task)
|
||||
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
# elif action.type == 'stop':
|
||||
# self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
# self._count += 1
|
||||
# if self.check_running_task_not_run() == True:
|
||||
# self._task_manager.running_task.stop()
|
||||
|
||||
elif action.type == 'idle':
|
||||
self._task_manager.running_task.stop()
|
||||
|
||||
instruction_set = None
|
||||
|
||||
if action.target is not None:
|
||||
device = self._complete_device[action.target]
|
||||
if ((action.type == 'start' and device.status == 0) or (action.type == 'stop' and device.status == 1)):
|
||||
self.log_verbose('Project' + self.name + 'Task ' + task.name + ' match_condition ' + condition.type + ' trigger_action ' + action.type + ' ' + str(action.target))
|
||||
task_info = task.get_task_info(action)
|
||||
instruction_set = getattr(self._instruction_set, action.type, None)
|
||||
|
||||
# 檔名修正
|
||||
# device
|
||||
task_info['file_name'] += '#' + device.mac_address_in_str[12:].upper()
|
||||
# 流水號
|
||||
task_info['file_name'] += '#' + str(self._count)
|
||||
|
||||
# 添加cycle資訊
|
||||
if len(self.cycle) > 0:
|
||||
index = self._task_manager.get_index_by_task(task)
|
||||
# get list of cycle determine by index of task
|
||||
filtered = list(filter(lambda info: self._task_manager.get_index_by_uuid(info['range'][0]) < index and self._task_manager.get_index_by_uuid(info['range'][1]) > index, self.cycle))
|
||||
|
||||
if len(filtered) == 0:
|
||||
pass
|
||||
elif len(filtered) == 1:
|
||||
if filtered[0]['useID'] == True:
|
||||
task_info['file_name'] += '#' + str(filtered[0]['id'])
|
||||
else:
|
||||
task_info['file_name'] += '#' + str(filtered[0]['name']) + '-' + str(filtered[0]['count'])
|
||||
else:
|
||||
# if multi cycle, then sort by range from task index to cycle start index, then loop concat filename
|
||||
filtered.sort(key=lambda info: abs(self._task_manager.get_index_by_uuid(info['range'][0]) - index))
|
||||
for cycle_info in filtered:
|
||||
if cycle_info['useID'] == True:
|
||||
task_info['file_name'] += '#' + str(cycle_info['id'])
|
||||
else:
|
||||
task_info['file_name'] += '#' + str(cycle_info['name']) + '-' + str(cycle_info['count'])
|
||||
self.log_verbose('file name ' + task_info['file_name'])
|
||||
|
||||
if instruction_set != None and len(task.parameter_set) > 0:
|
||||
if action.type == 'start':
|
||||
self._count += 1
|
||||
for instruction in instruction_set:
|
||||
print('instruction 1', device, instruction, datetime.now())
|
||||
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
|
||||
target=getattr(device, instruction['method'])(*args)
|
||||
print('instruction 2', device, instruction, datetime.now())
|
||||
|
||||
delay_time += (time() - now)
|
||||
|
||||
# check task not running then stop
|
||||
if self.check_running_task_not_run() == True:
|
||||
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])
|
||||
if self._task_manager.running_task.type == '':
|
||||
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
self._task_manager.running_task.stop()
|
||||
|
||||
# check project done then close project
|
||||
@@ -180,6 +254,8 @@ 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
|
||||
@@ -188,6 +264,8 @@ class Project(threading.Thread):
|
||||
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
||||
|
||||
def close(self):
|
||||
for device in self._complete_device:
|
||||
self._complete_device[device].occupied_by_project = None
|
||||
self._status = 2
|
||||
self._end_time = time()
|
||||
self._stop_flag = True
|
||||
@@ -200,11 +278,34 @@ 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
|
||||
@@ -222,6 +323,19 @@ class Project(threading.Thread):
|
||||
'status': self._status,
|
||||
'device': self._device,
|
||||
'task': self.task_list,
|
||||
'running_task': running_task
|
||||
'running_task': running_task,
|
||||
'cycle': self._cycle,
|
||||
'count': self._count,
|
||||
}
|
||||
return data
|
||||
|
||||
def info_pass_data_server(self):
|
||||
if self._task_manager.running_task is not None:
|
||||
running_task = self._task_manager.running_task.as_json()
|
||||
data = {
|
||||
'project': self._uuid,
|
||||
'task': running_task,
|
||||
'cycle': self._cycle,
|
||||
'serial_number': self._count,
|
||||
}
|
||||
return data
|
||||
|
||||
@@ -9,13 +9,14 @@ def json_stringify(o: Any) -> str:
|
||||
return _json_stringify(o, separators=(',', ':'))
|
||||
|
||||
class ProjectManager():
|
||||
def __init__(self, device_manager: DeviceManager, mqtt_thread=None) :
|
||||
def __init__(self, device_manager: DeviceManager, mqtt_thread=None, log_verbose = None) :
|
||||
self._project_list = []
|
||||
self._mqtt_thread = mqtt_thread
|
||||
self._device_manager = device_manager
|
||||
self.log_verbose = log_verbose
|
||||
|
||||
def create(self, project):
|
||||
new_project = Project(project, self._device_manager, self._mqtt_thread)
|
||||
new_project = Project(project, self._device_manager, self._mqtt_thread, self.log_verbose)
|
||||
self._project_list.append(new_project)
|
||||
return new_project
|
||||
|
||||
@@ -37,3 +38,11 @@ class ProjectManager():
|
||||
def stop_project(self, project):
|
||||
_project = self.get(project)
|
||||
_project.stop()
|
||||
|
||||
def set_project(self, project_uuid, content):
|
||||
_project = self.get(project_uuid)
|
||||
_project.set_content(content)
|
||||
|
||||
def set_project_cycle(self, project_uuid, index, content):
|
||||
_project = self.get(project_uuid)
|
||||
_project.set_cycle(index, content)
|
||||
|
||||
@@ -12,29 +12,39 @@ key_list = {
|
||||
class Task:
|
||||
def __init__(self, task):
|
||||
self._id = None
|
||||
self._uuid = None
|
||||
self._type = None
|
||||
self._name = None
|
||||
self._parent = None
|
||||
self._cycle = None
|
||||
self._cycle_count = 0
|
||||
self._cycle_next = None
|
||||
self._cycle_next_uuid = None
|
||||
self._device = None
|
||||
self._event = None
|
||||
self._trigger = None
|
||||
self._parameter_set = None
|
||||
self._condition = None
|
||||
self._action = None
|
||||
# -1: initial 0: start(idle), 1: running, 2: close(idle)
|
||||
# -1: init 0: start(idle), 1: run, 2: close(idle)
|
||||
self._status = 0
|
||||
self._next = None
|
||||
|
||||
# action & condition info
|
||||
self._condition_list: List[Condition] = []
|
||||
self._action_list: List[Action] = []
|
||||
self._instruction_list = []
|
||||
self._record_list = []
|
||||
|
||||
# time info
|
||||
self._start_time = []
|
||||
self._idle_time = []
|
||||
self._end_time = []
|
||||
self._period = None
|
||||
|
||||
# trigger info
|
||||
self._button_trigger = False
|
||||
|
||||
self.load_task(task)
|
||||
|
||||
def load_task(self, task) -> None:
|
||||
@@ -74,6 +84,14 @@ class Task:
|
||||
@uuid.setter
|
||||
def uuid(self, new_uuid):
|
||||
self._uuid = new_uuid
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
||||
@type.setter
|
||||
def type(self, new_type):
|
||||
self._type = new_type
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -100,6 +118,31 @@ class Task:
|
||||
@cycle.setter
|
||||
def cycle(self, new_cycle):
|
||||
self._cycle = new_cycle
|
||||
|
||||
# TODO: not sure needed?
|
||||
@property
|
||||
def cycle_count(self) -> int:
|
||||
return self._cycle_count
|
||||
|
||||
@cycle_count.setter
|
||||
def cycle_count(self, new_cycle_count):
|
||||
self._cycle_count = new_cycle_count
|
||||
|
||||
@property
|
||||
def cycle_next(self) -> str:
|
||||
return self._cycle_next
|
||||
|
||||
@cycle_next.setter
|
||||
def cycle_next(self, new_cycle_next):
|
||||
self._cycle_next = new_cycle_next
|
||||
|
||||
@property
|
||||
def cycle_next_uuid(self) -> str:
|
||||
return self._cycle_next_uuid
|
||||
|
||||
@cycle_next_uuid.setter
|
||||
def cycle_next_uuid(self, new_cycle_next_uuid):
|
||||
self._cycle_next_uuid = new_cycle_next_uuid
|
||||
|
||||
@property
|
||||
def device(self) -> dict:
|
||||
@@ -177,6 +220,14 @@ class Task:
|
||||
def end_time(self) -> List:
|
||||
return self._end_time
|
||||
|
||||
@property
|
||||
def button_trigger(self) -> List:
|
||||
return self._button_trigger
|
||||
|
||||
@button_trigger.setter
|
||||
def button_trigger(self, button_trigger):
|
||||
self._button_trigger = button_trigger
|
||||
|
||||
def new_start_time(self):
|
||||
self._start_time.append(time())
|
||||
|
||||
@@ -207,6 +258,10 @@ class Task:
|
||||
|
||||
def stop(self):
|
||||
self.status = 2
|
||||
|
||||
def reset(self):
|
||||
self.status = -1
|
||||
# self.status = 0
|
||||
|
||||
def get_match_action_list(self, match_condition_list):
|
||||
return map(lambda condition: [x for x in self._action_list if condition.id in x.get_condition_list()], match_condition_list)
|
||||
@@ -230,7 +285,7 @@ class Task:
|
||||
return {
|
||||
'device': action.target,
|
||||
'parameter': self.get_parameter_set_by_device(action.target),
|
||||
'file_name': self._name + '-' + str(action.target),
|
||||
'file_name': self._name,
|
||||
'parent': self.parent,
|
||||
'instruction': _type
|
||||
}
|
||||
@@ -240,7 +295,12 @@ class Task:
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'parent': self.parent,
|
||||
'type': self.type,
|
||||
'uuid': self.uuid,
|
||||
'cycle': self.cycle,
|
||||
'cycle_count': self.cycle_count,
|
||||
'cycle_next': self.cycle_next,
|
||||
'cycle_next_uuid': self.cycle_next_uuid,
|
||||
'device': self.device,
|
||||
'event': self.event,
|
||||
'trigger': self.trigger,
|
||||
|
||||
@@ -12,11 +12,12 @@ def json_stringify(o: Any) -> str:
|
||||
return _json_stringify(o, separators=(',', ':'))
|
||||
|
||||
class TaskManager():
|
||||
def __init__(self, task_list):
|
||||
def __init__(self, task_list, cycle_list):
|
||||
self._task_list = []
|
||||
self._next_task = []
|
||||
self._prev_task = None
|
||||
self._running_task = None
|
||||
self._cycle_list = cycle_list
|
||||
|
||||
self.load_task_list(task_list)
|
||||
|
||||
@@ -44,6 +45,23 @@ 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_end(self, task):
|
||||
for index, cycle in enumerate(self._cycle_list):
|
||||
if cycle['range'][1] == task.uuid:
|
||||
return index
|
||||
|
||||
@property
|
||||
def check_list(self):
|
||||
return [self._running_task, *self._next_task]
|
||||
@@ -57,7 +75,8 @@ class TaskManager():
|
||||
task = Task(task)
|
||||
self._task_list.append(task)
|
||||
|
||||
def set_running_task(self, task):
|
||||
# original version
|
||||
""" def set_running_task(self, task):
|
||||
try:
|
||||
# if there is task running & same task active ,then reject
|
||||
if self._running_task != None and self._running_task.uuid == task.uuid:
|
||||
@@ -80,6 +99,51 @@ 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_index = self.check_task_is_cycle_end(task)
|
||||
if cycle_index is None:
|
||||
# print('next', self._running_task.name, self._running_task.next)
|
||||
for task_uuid in self._running_task.next:
|
||||
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
|
||||
if _task != None:
|
||||
_task.reset()
|
||||
self._next_task.append(_task)
|
||||
# print('self._next_task', self._next_task)
|
||||
else:
|
||||
# print('cycle', self._cycle_list[cycle_index])
|
||||
cycle = self._cycle_list[cycle_index]
|
||||
if int(cycle['count']) < int(cycle['max']):
|
||||
self._next_task.append(self.get_task_by_uuid(cycle['range'][0]))
|
||||
cycle['count'] += 1
|
||||
else:
|
||||
for task_uuid in self._running_task.next:
|
||||
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
|
||||
if _task != None:
|
||||
_task.reset()
|
||||
self._next_task.append(_task)
|
||||
cycle['count'] = 1
|
||||
|
||||
except RuntimeError as e:
|
||||
print(e)
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
'_dirty', '_last_modify_time', '_file_size_cache',
|
||||
'_recording_file_ch', '_recording_sub_file', '_size',
|
||||
'_parameter', '_parent', '_recording_file_name', '_recording_sub_mini', '_recording_mini_ch',
|
||||
'_raw_serial_number', '_mini_serial_number', '_device_id')
|
||||
'_raw_serial_number', '_mini_serial_number', '_device_id', '_project_id')
|
||||
|
||||
def __init__(self, filepath: Union[str, Path], data_format: bytes = None, id_db = 0, database = None):
|
||||
if isinstance(filepath, str):
|
||||
@@ -153,6 +153,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
self._parent = ''
|
||||
self._recording_file_name = ''
|
||||
self._device_id = -1
|
||||
self._project_id = None
|
||||
|
||||
# recording parameter
|
||||
self._configuration = None
|
||||
@@ -297,6 +298,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
'uuid': str(self._file_uuid),
|
||||
'data_format': 'rec',
|
||||
'device': self._device,
|
||||
'project': self._project_id,
|
||||
}
|
||||
|
||||
if len(self._parent) > 0:
|
||||
@@ -462,7 +464,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def parameter(self) -> str:
|
||||
return self._parameter
|
||||
|
||||
@device.setter
|
||||
@parameter.setter
|
||||
def parameter(self, parameter):
|
||||
self._parameter = parameter
|
||||
return None
|
||||
@@ -471,7 +473,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def parent(self) -> str:
|
||||
return self._parent
|
||||
|
||||
@device.setter
|
||||
@parent.setter
|
||||
def parent(self, parent):
|
||||
self._parent = parent
|
||||
|
||||
@@ -479,7 +481,7 @@ class RecordingMetaFile(JsonSerialize):
|
||||
def recording_file_name(self) -> str:
|
||||
return self._recording_file_name
|
||||
|
||||
@device.setter
|
||||
@recording_file_name.setter
|
||||
def recording_file_name(self, recording_file_name):
|
||||
self._recording_file_name = recording_file_name
|
||||
|
||||
@@ -492,6 +494,15 @@ class RecordingMetaFile(JsonSerialize):
|
||||
self._configuration = conf
|
||||
self._dirty = True
|
||||
return None
|
||||
|
||||
@property
|
||||
def project_id(self) -> int:
|
||||
return self._project_id
|
||||
|
||||
@project_id.setter
|
||||
def project_id(self, project: int):
|
||||
self._project_id = project
|
||||
return None
|
||||
|
||||
@property
|
||||
def channels(self) -> List[int]:
|
||||
|
||||
@@ -4,7 +4,6 @@ from time import time, sleep
|
||||
from typing import Iterable
|
||||
from datetime import datetime
|
||||
import gc
|
||||
|
||||
import base64
|
||||
|
||||
from biopro.data import *
|
||||
@@ -27,7 +26,6 @@ from .mqtt import MqttDataMessageHandler, MqttThread
|
||||
from .database import DataBaseProcess
|
||||
from .recording import RecordingProcess
|
||||
from multiprocessing import Queue
|
||||
import queue
|
||||
|
||||
from json import loads as json_parse, dumps as _json_stringify
|
||||
import json
|
||||
@@ -65,7 +63,7 @@ class DataServer(SocketServer, DataAPI):
|
||||
"""
|
||||
global _FLAG_DATA_LOST_STATS_
|
||||
|
||||
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=3)
|
||||
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=20)
|
||||
|
||||
data_options = DataServerOptions.get_options(*options)
|
||||
|
||||
@@ -317,7 +315,8 @@ class DataServer(SocketServer, DataAPI):
|
||||
def update_device_configuration(self,
|
||||
device: str,
|
||||
meta_file: Union[str, Path, RecordingMetaFile],
|
||||
data_format: Union[AnyStr, DataDecodeFormat]):
|
||||
data_format: Union[AnyStr, DataDecodeFormat],
|
||||
project_info: str):
|
||||
# meta file
|
||||
|
||||
device_id = -1
|
||||
@@ -345,6 +344,8 @@ class DataServer(SocketServer, DataAPI):
|
||||
_parent = json_stringify(_device['parent'])
|
||||
_recording_file_name = _device['recording_file_name']
|
||||
mac_address = json.loads(device)['device_address']
|
||||
device_id = _device['device_id']
|
||||
|
||||
del _device['configuration']
|
||||
del _device['parent']
|
||||
del _device['recording_file_name']
|
||||
@@ -354,13 +355,22 @@ class DataServer(SocketServer, DataAPI):
|
||||
# meta_file.parameter = _parameter
|
||||
# meta_file.parent = _parent
|
||||
# meta_file.recording_file_name = _recording_file_name
|
||||
device_id = int(json.loads(device)['device_id'])
|
||||
|
||||
if device_id < 0:
|
||||
raise ValueError('illegal device ID : ' + str(device_id))
|
||||
|
||||
self.log_verbose('device ID', device_id)
|
||||
|
||||
# project binding meta file
|
||||
project_id = None
|
||||
_project = None
|
||||
if project_info != None:
|
||||
_project = json.loads(project_info)
|
||||
self.database_process.put_queue(['project_insert', device_id, _project])
|
||||
result = self._queue_ds_dict[int(device_id)].get()
|
||||
if result[0] == 'project_id':
|
||||
project_id = result[1]
|
||||
|
||||
# while len(self._configurations) <= device_id:
|
||||
# self._configurationsappend(None)
|
||||
|
||||
@@ -380,8 +390,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
else:
|
||||
data_format = data_format.name
|
||||
|
||||
# self.log_verbose('device data format', data_format)
|
||||
|
||||
self.log_verbose('device meta file', meta_file)
|
||||
|
||||
# data runtime
|
||||
@@ -406,15 +414,15 @@ class DataServer(SocketServer, DataAPI):
|
||||
c.shutdown()
|
||||
c.join()
|
||||
self._spi.set_wait_flag(c._device, True)
|
||||
|
||||
data_runtime_process = RecordingProcess('data_server', self.log_verbose, device_id,
|
||||
Queue(), self._queue_ds_dict[int(device_id)], self._queue_msg, meta_file,
|
||||
json_stringify(_device), _parameter, _parent, _recording_file_name,
|
||||
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
|
||||
database = self.database_process )
|
||||
# data_runtime_process.start()
|
||||
data_format, self.socket_mqtt_ip, self.socket_mqtt_port,
|
||||
project_id = project_id,
|
||||
database = self.database_process)
|
||||
|
||||
# check channel
|
||||
|
||||
if isinstance(data_runtime_process, RecordingProcess) and device_id not in self._available_channel:
|
||||
raise RuntimeError('set device configuration on un-available channel', device_id)
|
||||
|
||||
@@ -646,6 +654,7 @@ class DataServer(SocketServer, DataAPI):
|
||||
def whether_to_record(self, device):
|
||||
# if user click "start", return True; if user click "stop", return False;
|
||||
if device in self._configurations.keys() and self._configurations[device] is not None:
|
||||
# print(self._configurations.keys(), ',', device, datetime.now())
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -654,6 +663,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
ret = False
|
||||
sync = self.get_spi_obj()
|
||||
|
||||
busy = sync.get_pin_busy()
|
||||
# print('pin_busy=', busy, device, datetime.now())
|
||||
|
||||
if sync.get_pin_mem_req() == sync.get_pin_ram_sel():
|
||||
spi_data = sync.recv_memory(device)
|
||||
signal = sync.get_pin_mem_req()
|
||||
@@ -662,15 +674,18 @@ class DataServer(SocketServer, DataAPI):
|
||||
|
||||
else:
|
||||
data = None
|
||||
print('data=None, mem_req!=ram_sel, [', sync.get_pin_mem_req(), ', ', sync.get_pin_ram_sel(), ']', device, datetime.now())
|
||||
|
||||
if data is not None:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
# self._no_data_total_duration = 0
|
||||
ret = True
|
||||
if self._configurations.get(device, None) != None:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
if self._configurations.get(device, None) != None:
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
# self._no_data_total_duration = 0
|
||||
ret = True
|
||||
# else:
|
||||
# time_diff = time() - self._recv_memory_cost_time
|
||||
# self._no_data_total_duration += time_diff
|
||||
@@ -699,6 +714,9 @@ class DataServer(SocketServer, DataAPI):
|
||||
self.mqtt_thread.publish('device_instruction', json_stringify(content), inter = True)
|
||||
|
||||
return True
|
||||
|
||||
def show_data(self, device):
|
||||
self._configurations[device].put_rec_queue('show_data')
|
||||
|
||||
class DataRuntime(metaclass=abc.ABCMeta):
|
||||
__slots__ = ('_server', '_device', '_meta_file', '_data_format',
|
||||
|
||||
@@ -550,4 +550,33 @@ class DataBaseProcess(Process):
|
||||
except psycopg2.Error as e:
|
||||
print('e', e)
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def project_insert(self, device_id, _data):
|
||||
sql_str = 'INSERT INTO "public"."meta_project_info" ('
|
||||
sql_set = []
|
||||
for item in _data.keys():
|
||||
sql_str = sql_str + str(item) + ', '
|
||||
if isinstance(_data[item], dict) or isinstance(_data[item], list):
|
||||
sql_set.append(json_stringify(_data[item]))
|
||||
else:
|
||||
sql_set.append(_data[item])
|
||||
|
||||
sql_str = sql_str[0:-2] + ') VALUES ('
|
||||
for item in _data.keys():
|
||||
sql_str = sql_str + '%s, '
|
||||
|
||||
sql_str = sql_str[0:-2] + ') RETURNING id'
|
||||
sql_cursor = self._psql_conn.cursor()
|
||||
|
||||
try:
|
||||
sql_cursor.execute(sql_str, sql_set)
|
||||
except BaseException as e:
|
||||
print('insert error', e)
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
self._queue_error.put()
|
||||
finally:
|
||||
self._queue_ds[int(device_id)].put(['project_id', int(sql_cursor.fetchone()[0])])
|
||||
self._psql_conn.commit()
|
||||
sql_cursor.close()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from time import sleep
|
||||
from typing import Iterable
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
import biopro.impl.vcgencmd as vcg
|
||||
from biopro.data import DataServerOptions, DataAPI
|
||||
@@ -31,8 +32,10 @@ from biopro.api.auth import AuthAPI
|
||||
from biopro.api.controller import ControllerAPI
|
||||
from biopro.api.device import DeviceAPI
|
||||
from biopro.project.project_manager import ProjectManager
|
||||
### do not import Websocket mode
|
||||
###from .websocket import WebsocketThread
|
||||
from biopro.db.base import Base, Session, engine
|
||||
from biopro.db.project_report import ProjectReport
|
||||
from biopro.db.meta_project_info import MetaProjectInfo
|
||||
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
@@ -105,7 +108,7 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
# device detect
|
||||
self._detect_device_thread = RoutineConnectDeviceThread(self._device_manager, self.mqtt_thread, self.led_thread, 3)
|
||||
|
||||
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread)
|
||||
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread, self.log_verbose)
|
||||
|
||||
if not c.flag_disable_led_control:
|
||||
self.led_thread.set_state(LED.COLOR_RED)
|
||||
@@ -117,8 +120,8 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
self.ups_thread = UPSDetectThread(self, c.flag_ups_wait_time)
|
||||
|
||||
# user session
|
||||
self._session = {}
|
||||
self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
|
||||
# self._session = {}
|
||||
# self._user_session_expire = c.user_session_expire_days * 24 * 60 * 60 # sec
|
||||
|
||||
# indicate those device together
|
||||
self._device_instruction_group = None
|
||||
@@ -129,6 +132,10 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
# _api request build
|
||||
self._api = ApiRequests()
|
||||
|
||||
# sqlalchemy
|
||||
Base.metadata.create_all(engine)
|
||||
self._session = Session()
|
||||
|
||||
# init method
|
||||
|
||||
def _init_file_manager(self, option: ControlServerOptions) -> FileManager:
|
||||
@@ -819,12 +826,21 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def device_battery(self) -> List[int]:
|
||||
device_list = self.device_manager.list_device()
|
||||
if len(device_list) > 0:
|
||||
battery_list = list(map(lambda x: self.device_manager.get_device(x).battery, device_list))
|
||||
|
||||
return battery_list
|
||||
def device_battery(self, device:int) -> List[int]:
|
||||
try:
|
||||
battery = {}
|
||||
if device == 'all':
|
||||
device_list = self.device_manager.list_device()
|
||||
if len(device_list) > 0:
|
||||
battery = list(map(lambda x: {"device": x.memory_board, "battery":self.device_manager.get_device(x).battery}, device_list))
|
||||
else:
|
||||
battery = {
|
||||
"device": device,
|
||||
"battery": self.device_manager.get_device(device).battery
|
||||
}
|
||||
except AttributeError as e:
|
||||
print('device_battery', device, 'not found', e)
|
||||
return battery
|
||||
|
||||
@logging_info
|
||||
def device_parent(self, device: int, content: Optional[str] = None) -> List[int]:
|
||||
@@ -1016,6 +1032,16 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
def run_project(self, project) -> bool:
|
||||
if project is not None:
|
||||
project = self._project_manager.create(project)
|
||||
with self._session as session:
|
||||
project_report = ProjectReport(
|
||||
name = project.name,
|
||||
uuid = project.uuid,
|
||||
cycle = project.cycle,
|
||||
task = project.task_list,
|
||||
device = project.device
|
||||
)
|
||||
session.add(project_report)
|
||||
session.commit()
|
||||
self._project_manager.run_project(project)
|
||||
return project.as_json()
|
||||
|
||||
@@ -1024,6 +1050,18 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
if project is not None:
|
||||
self._project_manager.stop_project(project)
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def set_project(self, project, content) -> bool:
|
||||
if project is not None:
|
||||
self._project_manager.set_project(project, content)
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def set_project_cycle(self, project, index, content) -> bool:
|
||||
if project is not None:
|
||||
self._project_manager.set_project_cycle(project, index, content)
|
||||
return True
|
||||
|
||||
@logging_info
|
||||
def get_running_project(self) -> bool:
|
||||
@@ -1059,6 +1097,7 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
self.log_verbose('update data format', value)
|
||||
|
||||
client = self.data_server.client()
|
||||
project = None
|
||||
if client is not None:
|
||||
info = self.file_manager.use(device)
|
||||
|
||||
@@ -1069,9 +1108,12 @@ 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 = json.dumps(self.project_manager.get(device.occupied_by_project).info_pass_data_server())
|
||||
|
||||
with client:
|
||||
client.update_device_configuration(device, info.meta_file, value)
|
||||
client.update_device_configuration(device, info.meta_file, value, project)
|
||||
|
||||
def _device_set_disable_cache(self, device: CompletedDevice, disable):
|
||||
if disable:
|
||||
@@ -1105,7 +1147,6 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
filename = format_filename(self.TEMP_FILENAME_EXPR, device)
|
||||
info = self.file_manager.save(device, filename)
|
||||
client.update_device_configuration(device, info.meta_file, RawDataDecoder())
|
||||
|
||||
if self._device_instruction_group is None:
|
||||
client.start_sync(device)
|
||||
|
||||
@@ -1339,6 +1380,13 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
def _hardware_send_test_set(self, options: Dict[str, str]) -> bool:
|
||||
# TODO write options files
|
||||
return False
|
||||
|
||||
@logging_info
|
||||
def show_device_data(self, device: int):
|
||||
client = self.data_server.client()
|
||||
if client is not None:
|
||||
with client:
|
||||
client.show_data(device)
|
||||
|
||||
class _RandomCrashThread(ServerThread):
|
||||
def __init__(self):
|
||||
|
||||
@@ -44,7 +44,9 @@ class RecordingProcess(Process):
|
||||
def __init__(self, client_id: str, log_verbose, device_id, queue_rec, queue_ds, queue_msg, meta_path,
|
||||
device_info, parameter, parent, recording_file_name, data_format,
|
||||
mqtt_ip, mqtt_port,
|
||||
name = 'Recording-Process', database = None):
|
||||
name = 'Recording-Process',
|
||||
project_id = None,
|
||||
database = None):
|
||||
super(RecordingProcess, self).__init__(name = name)
|
||||
|
||||
self._database = database
|
||||
@@ -57,6 +59,7 @@ class RecordingProcess(Process):
|
||||
self._meta_file._parent = parent
|
||||
self._meta_file._recording_file_name = recording_file_name
|
||||
self._meta_file._device_id = device_id
|
||||
self._meta_file._project_id = project_id
|
||||
print(self._meta_file._device, self._meta_file._parameter, self._meta_file._parent, self._meta_file._filepath)
|
||||
self._meta_file.write(self._database)
|
||||
|
||||
@@ -185,6 +188,8 @@ class RecordingProcess(Process):
|
||||
self.final_write()
|
||||
self.is_closed = True
|
||||
return False
|
||||
elif q == 'show_data':
|
||||
self._decoder._show_data = not self._decoder._show_data
|
||||
else:
|
||||
self.rec_update()
|
||||
self.sync_data(q)
|
||||
|
||||
@@ -93,13 +93,15 @@ class SocketClient(metaclass=abc.ABCMeta):
|
||||
if self._socket is None:
|
||||
try:
|
||||
self._socket = Socket(AF_UNIX, SOCK_STREAM)
|
||||
self._socket.settimeout(1)
|
||||
self._socket.settimeout(5)
|
||||
self._socket.connect(self._socket_file)
|
||||
except FileNotFoundError as e:
|
||||
raise RuntimeError('server not available') from e
|
||||
except Exception as e:
|
||||
print('open_socket error:', e)
|
||||
# except FileNotFoundError as e:
|
||||
# raise RuntimeError('server not available') from e
|
||||
|
||||
except ConnectionRefusedError as e:
|
||||
raise RuntimeError('server crash') from e
|
||||
# except ConnectionRefusedError as e:
|
||||
# raise RuntimeError('server crash') from e
|
||||
|
||||
def close_socket(self):
|
||||
if self._socket is not None:
|
||||
|
||||
@@ -1203,7 +1203,7 @@
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X07;",
|
||||
"X0C;",
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
|
||||
@@ -15,6 +15,33 @@
|
||||
"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,
|
||||
@@ -671,6 +698,17 @@
|
||||
},
|
||||
"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"
|
||||
@@ -836,6 +874,18 @@
|
||||
],
|
||||
"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,
|
||||
@@ -851,7 +901,8 @@
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"Iin",
|
||||
"Vin"
|
||||
"Vin",
|
||||
"Vout"
|
||||
]
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
@@ -912,11 +963,13 @@
|
||||
"_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"
|
||||
"1": "cali_Vin",
|
||||
"2": "cali_Vout"
|
||||
}
|
||||
},
|
||||
"_sync(True)",
|
||||
@@ -1007,12 +1060,6 @@
|
||||
"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": [
|
||||
@@ -1025,6 +1072,12 @@
|
||||
"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": [
|
||||
@@ -1052,6 +1105,15 @@
|
||||
"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": {
|
||||
@@ -1203,7 +1265,7 @@
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X07;",
|
||||
"X0C;",
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
|
||||
@@ -15,6 +15,33 @@
|
||||
"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,
|
||||
@@ -671,6 +698,17 @@
|
||||
},
|
||||
"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"
|
||||
@@ -836,6 +874,18 @@
|
||||
],
|
||||
"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,
|
||||
@@ -851,7 +901,8 @@
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"Iin",
|
||||
"Vin"
|
||||
"Vin",
|
||||
"Vout"
|
||||
]
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
@@ -912,11 +963,13 @@
|
||||
"_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"
|
||||
"1": "cali_Vin",
|
||||
"2": "cali_Vout"
|
||||
}
|
||||
},
|
||||
"_sync(True)",
|
||||
@@ -1007,12 +1060,6 @@
|
||||
"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": [
|
||||
@@ -1025,6 +1072,12 @@
|
||||
"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": [
|
||||
@@ -1052,6 +1105,15 @@
|
||||
"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": {
|
||||
@@ -1203,7 +1265,7 @@
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X07;",
|
||||
"X0C;",
|
||||
"B>va;4B>vb;2B>vc;2B>vd;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>pc;4b>pd;",
|
||||
|
||||
@@ -15,6 +15,33 @@
|
||||
"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,
|
||||
@@ -671,6 +698,17 @@
|
||||
},
|
||||
"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"
|
||||
@@ -836,6 +874,18 @@
|
||||
],
|
||||
"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,
|
||||
@@ -851,7 +901,8 @@
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"Iin",
|
||||
"Vin"
|
||||
"Vin",
|
||||
"Vout"
|
||||
]
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
@@ -912,11 +963,13 @@
|
||||
"_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"
|
||||
"1": "cali_Vin",
|
||||
"2": "cali_Vout"
|
||||
}
|
||||
},
|
||||
"_sync(True)",
|
||||
@@ -1007,12 +1060,6 @@
|
||||
"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": [
|
||||
@@ -1025,6 +1072,12 @@
|
||||
"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": [
|
||||
@@ -1052,6 +1105,15 @@
|
||||
"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": {
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Chronoamperometric",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
@@ -69,7 +70,7 @@
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13422819,
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
@@ -265,6 +266,17 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_VSCAN": {
|
||||
"description": "Voltage of VScan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
"description": "send msg to elite",
|
||||
"domain": {
|
||||
@@ -295,20 +307,23 @@
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_I"
|
||||
"1": "set_adc_gain_I",
|
||||
"2": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_Vin"
|
||||
"1": "set_adc_gain_Vin",
|
||||
"2": "set_adc_gain_Vin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3"
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_const_vscan"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -424,6 +439,23 @@
|
||||
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_const_vscan": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_VSCAN",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1XD3;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
|
||||
@@ -62,6 +62,9 @@
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Chronoamperometric",
|
||||
"V-T Graph",
|
||||
"R-T Graph",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
@@ -69,7 +72,7 @@
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13422819,
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
@@ -265,6 +268,39 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_VSCAN": {
|
||||
"description": "Voltage of VScan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"MEASURE_VIN_RANGE": {
|
||||
"description": "measure range of Vin",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"auto"
|
||||
]
|
||||
},
|
||||
"DAC_VOLT": {
|
||||
"description": "DAC output Voltage",
|
||||
"record_meta": true,
|
||||
"initial": 37500,
|
||||
"domain": [
|
||||
65536
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
"description": "send msg to elite",
|
||||
"domain": {
|
||||
@@ -295,20 +331,29 @@
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_I"
|
||||
"1": "set_adc_gain_I",
|
||||
"2": "set_adc_gain_I",
|
||||
"3": "set_adc_gain_I",
|
||||
"4": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_Vin"
|
||||
"1": "set_adc_gain_Vin",
|
||||
"2": "set_adc_gain_Vin",
|
||||
"3": "set_adc_gain_Vin",
|
||||
"4": "set_adc_gain_Vin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3"
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_const_vscan",
|
||||
"3": "curve_vt",
|
||||
"4": "curve_zt"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -424,6 +469,57 @@
|
||||
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_const_vscan": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_VSCAN",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1XD3;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_zt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "DAC_VOLT",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"X04;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_vt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE",
|
||||
"va": "MEASURE_VIN_RANGE"
|
||||
},
|
||||
"data": [
|
||||
"X05;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe;",
|
||||
"1B>va"
|
||||
]
|
||||
},
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
"value": [
|
||||
"EIS CURVE",
|
||||
"Cyclic Voltammetry",
|
||||
"Chronoamperometric",
|
||||
"V-T Graph",
|
||||
"Dev Mode"
|
||||
]
|
||||
},
|
||||
@@ -69,7 +71,7 @@
|
||||
"description": "DPV current recording period start",
|
||||
"record_meta": true,
|
||||
"initial": [
|
||||
13422819,
|
||||
13333333,
|
||||
7
|
||||
],
|
||||
"domain": {
|
||||
@@ -265,6 +267,28 @@
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"VOLT_VSCAN": {
|
||||
"description": "Voltage of VScan",
|
||||
"record_meta": true,
|
||||
"initial": 25000,
|
||||
"domain": [
|
||||
"VOLT_MAX"
|
||||
],
|
||||
"value": {
|
||||
"expression": "VALUE"
|
||||
}
|
||||
},
|
||||
"MEASURE_VIN_RANGE": {
|
||||
"description": "measure range of Vin",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"value": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"auto"
|
||||
]
|
||||
},
|
||||
"BLE_WRITE": {
|
||||
"description": "send msg to elite",
|
||||
"domain": {
|
||||
@@ -295,20 +319,26 @@
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_I"
|
||||
"1": "set_adc_gain_I",
|
||||
"2": "set_adc_gain_I",
|
||||
"3": "set_adc_gain_I"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"1": "set_adc_gain_Vin"
|
||||
"1": "set_adc_gain_Vin",
|
||||
"2": "set_adc_gain_Vin",
|
||||
"3": "set_adc_gain_Vin"
|
||||
}
|
||||
},
|
||||
{
|
||||
"expression": "MODE",
|
||||
"when": {
|
||||
"0": "curve_eis",
|
||||
"1": "curve_cv3"
|
||||
"1": "curve_cv3",
|
||||
"2": "curve_const_vscan",
|
||||
"3": "curve_vt"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -424,6 +454,40 @@
|
||||
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
|
||||
]
|
||||
},
|
||||
"curve_const_vscan": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"va": "VOLT_VSCAN",
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE"
|
||||
},
|
||||
"data": [
|
||||
"1XD3;",
|
||||
"2B>va;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe"
|
||||
]
|
||||
},
|
||||
"curve_vt": {
|
||||
"type": "RIS",
|
||||
"parameter": {
|
||||
"pa": "ADC_LEVEL_I_15",
|
||||
"pb": "ADC_LEVEL_V_IN_15",
|
||||
"pd": "CTRL_HIGH_Z_15",
|
||||
"pe": "SAMPLE_RATE",
|
||||
"va": "MEASURE_VIN_RANGE"
|
||||
},
|
||||
"data": [
|
||||
"X05;",
|
||||
"4b>pa;4b>pb;",
|
||||
"4b>0;4b>pd;",
|
||||
"2B>pe;",
|
||||
"1B>va"
|
||||
]
|
||||
},
|
||||
"ble_instru_send": [
|
||||
"ble_write",
|
||||
"_cdr('20X>ADC_VALUE_I')"
|
||||
|
||||
Reference in New Issue
Block a user