Compare commits

..

9 Commits

Author SHA1 Message Date
peterlu14 2edb6cb8a9 -fix DetachedInstanceError 2023-06-07 13:35:36 +08:00
peterlu14 32bf5d3b11 -update add subject write in same folder 2023-06-07 11:38:15 +08:00
peterlu14 66c7744d7e -update db_update_script 2023-06-05 17:35:52 +08:00
peterlu14 585e50bf5b -fix import error 2023-06-05 17:34:34 +08:00
peterlu14 f643b6f194 -update subject 2023-06-05 14:46:38 +08:00
peterlu14 d4cec103ab - fix UnboundLocalError : 'project_meta_id' 2023-06-05 14:44:24 +08:00
peterlu14 23e66b265c - update create meta project info change from data-server to control-server 2023-06-05 14:44:18 +08:00
peterlu14 741d6bcb9f - update create collection table
- init project then create folder
2023-06-05 14:44:10 +08:00
Roy f53f9acccb fix DC Iin problem 2023-01-05 12:59:43 +08:00
26 changed files with 963 additions and 3412 deletions
+30 -15
View File
@@ -20,29 +20,44 @@ class Collection(Base):
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_collection(cls, collection_name, parent):
def create_collection(cls, collection_name, parent, duplicate=False):
with Session() as session:
name = cls.check_name_duplicate(collection_name, parent, 0)
collection = Collection(
name = name,
parent = parent,
type= "folder",
)
session.add(collection)
session.commit()
print('a', collection.id)
return collection
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):
with Session() as session:
result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
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)
return cls.check_name_duplicate(collection_name, parent, new_num, _session)
@classmethod
def generate_name(cls, collection_name, n):
-51
View File
@@ -1,51 +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, Float, BINARY, LargeBinary
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base, Session
class Device(Base):
__tablename__ = "devices"
id = Column(Integer, primary_key=True)
name = Column(String(255))
mac_address = Column(String(255))
serial_number = Column(String(255))
configuration = Column(JSONB)
library = Column(String(255))
library_version = Column(String(255))
device_version = Column(String(255))
type = Column(String(255))
battery = Column(Integer)
temperature = Column(Float)
auto_connect = Column(Boolean)
connect_priority = Column(Integer)
connect_time = Column(BigInteger)
parameter_set = Column(JSONB)
running = Column(Boolean)
calibration = Column(LargeBinary)
calibration_version = Column(Integer, default=-1)
user_auth = Column(JSONB)
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def update_device(cls, device, options):
with Session() as session:
result = session.query(Device).filter(Device.mac_address == device['mac_address']).first()
for key, value in options.items():
setattr(result, key, value)
session.commit()
@classmethod
def get_device(cls, device):
with Session() as session:
result = session.query(Device).filter(Device.mac_address == device['mac_address']).first()
return result
# def __repr__(self):
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
+24
View File
@@ -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, 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})"
+88
View File
@@ -0,0 +1,88 @@
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
@@ -0,0 +1,60 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
class 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
+374 -361
View File
@@ -350,7 +350,6 @@ class CC2650Device(Device):
self._recording_file_name: str = 'recording_data'
self._coeff: bytes = b''
self._device_version = ""
self._cali_version = -1
@property
def device_id(self) -> int:
@@ -433,12 +432,12 @@ class CC2650Device(Device):
if length == 1 and instruction[0] < 0:
return struct.pack('2B1b',
(ins_type & 0xF0) | (self.device_id & 0x0F),
(ins_oper & 0xFF),
(ins_oper & 0xF0) | (length & 0x0F),
*instruction)
return struct.pack('%dB' % (length + 2),
(ins_type & 0xF0) | (self.device_id & 0x0F),
(ins_oper & 0xFF),
(ins_oper & 0xF0) | (length & 0x0F),
*instruction)
def _decode_data(self, ins_oper: int, data: bytes) -> bytes:
@@ -478,24 +477,22 @@ class CC2650Device(Device):
else:
if data is not None and len(data) > 0:
year = struct.unpack('<B', data[2:3])[0]
month = struct.unpack('<B', data[3:4])[0]
day = struct.unpack('<B', data[4:5])[0]
hour = struct.unpack('<B', data[5:6])[0]
minute = struct.unpack('<B', data[6:7])[0]
# mac1 = struct.unpack('<B', data[7:8])[0]
# mac2 = struct.unpack('<B', data[8:9])[0]
# mac1 = "%02X" % mac1
# mac2 = "%02X" % mac2
year = struct.unpack('<B', data[0:1])[0]
month = struct.unpack('<B', data[1:2])[0]
day = struct.unpack('<B', data[2:3])[0]
hour = struct.unpack('<B', data[3:4])[0]
minute = struct.unpack('<B', data[4:5])[0]
mac1 = struct.unpack('<B', data[5:6])[0]
mac2 = struct.unpack('<B', data[6:7])[0]
mac1 = "%02X" % mac1
mac2 = "%02X" % mac2
self._device_version = str(year) + '/' + str(month) + '/' + str(day) + " " + str(hour) + ":" + str(
minute)
# + " | " + str(mac1) + ":" + str(mac2)
minute) + " | " + str(mac1) + ":" + str(mac2)
@property
def battery(self) -> int:
if self._start_flag == False:
self.update_battery_info()
self.update_battery_info()
return self._battery
@property
@@ -540,7 +537,7 @@ class CC2650Device(Device):
else:
if data is not None and len(data) > 2 :
battery = struct.unpack('<H', data[2:4])[0]
battery = struct.unpack('<H', data[1:3])[0]
if battery is not None:
self._battery = battery
@@ -552,39 +549,6 @@ class CC2650Device(Device):
self.update_calibration_info(device_type)
return self._coeff
def _check_crc(self, data):
data_chk_sum = data[-1]
# print('data:', list(data), 'data_chk_sum:', data_chk_sum)
# print('data[0:-1]:', list(data[0:-1]), 'check_sum:', sum(data[0:-1]) & 0b11111111)
if data_chk_sum == sum(data[0:-1]) & 0b11111111:
return True
return False
def update_cali_version(self) -> bool:
for _ in range(5):
try:
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, 0)
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
except SendInstructionTimeoutError:
self._master.log_warn('device', self.device_id, 'update cali version error')
return False
except RuntimeError:
self._master.log_warn('device', self.device_id, 'update cali version error')
return False
else:
version = self._master.read_characteristic(self.device_id,CC2650MasterDevice.RETURN_HANDLE)
if self._check_crc(version):
self._cali_version = struct.unpack('<H', version[2:4])[0]
print('self._cali_version=', self._cali_version)
return True
self._master.log_warn('device', self.device_id, 'update cali version error')
return False
def update_calibration_info(self, device_type: str):
""" get device calibration info """
@@ -607,6 +571,20 @@ class CC2650Device(Device):
elif device_type == 'TDC4VC':
i = 0
request_times = 0
# neulive 2.1 (only support ch1~ch8)
# try:
# # send
# code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, 0)
# self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
# # receive
# data = self._master.read_characteristic(self.device_id, CC2650MasterDevice.RETURN_HANDLE)
#
# coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
# except SendInstructionTimeoutError:
# self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
# except RuntimeError:
# self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
while i < 4:
try:
# print('i', i)
@@ -682,34 +660,43 @@ class CC2650Device(Device):
break
elif device_type == 'EISZeroOne':
i = 1
while i <= 24:
for _ in range(5):
try:
# send
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
i = 0
request_times = 0
while i < 13:
try:
# send
code = self._encode_instruction(DeviceInstruction.TYP_CIS, DeviceInstruction.CIS_CALI, i)
self._master.write_characteristic(self.device_id, CC2650MasterDevice.COMMAND_HANDLE, code)
except SerialTimeoutException:
self._master.log_warn('device', self.device_id, 'send update_calibration_info instruction fail')
continue
sleep(0.1)
# receive
data = self._master.read_characteristic(self.device_id,
CC2650MasterDevice.RETURN_HANDLE)
coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
except SendInstructionTimeoutError as e:
print(e)
self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
raise BaseException
except RuntimeError as e:
print(e)
self._master.log_warn('device', self.device_id, 'update_calibration_info no response - 2')
request_times += 1
if request_times > 3:
self._master.reset(self.device_id)
break
else:
# print('data success')
if len(data) > 0:
i += 1
else:
try:
# receive
data = self._master.read_characteristic(self.device_id,
CC2650MasterDevice.RETURN_HANDLE)
except RecvTimeout:
self._master.log_warn('device', self.device_id, 'update_calibration_info no response')
request_times += 1
if request_times > 3:
self._master.reset(self.device_id)
break
else:
if self._check_crc(data) and data is not None:
coeff.append(self._decode_data(DeviceInstruction.CIS_CALI, data))
i += 1
else:
self._master.log_warn('device', self.device_id, 'update_calibration_info crc wrong')
continue
else:
# default: neulive 2.1
for i in range(1):
@@ -1963,6 +1950,120 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
"""initialize cc2650 (master)"""
pass
def scan_send_ins(self):
# send scan command
try:
print(':: scan_send_ins ::', self.CC2650_COMMAND_LEN, 3, 0, 0)
self._cc2650.send(self.CC2650_COMMAND_LEN, 3, 0, 0)
except SerialTimeoutException as e:
raise RecvTimeout('send scan fail') from e
else:
# wait scanning
# sleep(2)
clean_buf = self._cc2650.receive_timeout("20B", timeout=3)
print("clean_buf = ", clean_buf)
# def cc2650_uart_irq(self):
# uart_irq = self.get_uart_irq_pin()
# uart_irq.output(False)
# sleep(0.001)
# uart_irq.output(True)
@synchronized
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
self._found = found = []
self._found_with_id = []
hdr_BPHS = [66, 80, 72, 83]
scan_response: Union[Optional[tuple], Any] = None
# build scan instruction
scan_ins = bytearray()
scan_ins.append(3) #scan instruction
scan_ins.append(1) #length
scan_ins.append(0xF1)
# print('send_scan', bytes(scan_ins))
self._cc2650.send("bytes", bytes(scan_ins))
try:
scan_response = self._cc2650.recv_uart(timeout)
except RecvTimeout:
# self.reset_internal()
# self.reset_hardware()
# self._interface.flush()
return False
# instruction format:
# ins[0]: get_scan_response = 0x04
# ins[1]: number of scanned device=0; a certain device = device_id (could be 1~8)
# ins[2]: addr=MAC=1, localName=2, company_code=3, version_info=4, battery_info=5, all_info=6;
# attr_length=0, e.g. len(addr)=6, len(company_code)=4
local_mac = None
local_cc = None
local_ver = None
local_bat = None
local_name = None
local_addr_type = None
# get device attribute length
attr_length = [6, 4, 6, 5, 20]
index = 0
local_mac = get_device_mac_in_address_format(scan_response[index:index + 6])
index = index + 6
# print("local_mac = ", hex(local_mac[0]), hex(local_mac[1]),
# hex(local_mac[2]), hex(local_mac[3]),
# hex(local_mac[4]), hex(local_mac[5]))
local_cc = get_device_company_code(scan_response[index:index + 4])
index = index + 4
# print("local_cc = ", local_cc)
local_ver = scan_response[index:index + 6]
index = index + 6
# print("local_ver = ", local_ver)
local_bat = get_device_battery_info(scan_response[index:index + 5])
index = index + 5
# print("local_bat = ", local_bat)
local_name = get_device_name_in_string_format(list(scan_response[index:index + 20]))
index = index + 20
# print("local_name = ", local_name)
# addr type is don't care in BMD380
print('scan_response:', list(scan_response))
local_addr_type = int(scan_response[index:index + 1][0])
# local_addr_type = 0xFF
index = index + 1
# print("local_addr_type = ", local_addr_type)
response = is_headstage_device_central_version(local_mac,
local_addr_type,
local_name,
local_cc,
local_ver,
local_bat)
if response is not None:
self.log_info('found', address_str(response.mac_address), response.serial_number)
self._interface.flush_input()
# apppend into db
devicesList = DeviceAPI.getByMac(address_str(response.mac_address))
if devicesList is not None:
if len(devicesList) == 0:
DeviceAPI.create(response.device_name, local_ver, address_str(response.mac_address))
found.append(response)
# print('scan_done_found', found)
self._found_with_id.append((response, 0 + 1))
callback(response)
return True
def decode_uart_preamble(self, raw_uart: tuple, expect_ret_len: int = 0) -> Optional[list]:
# print("decode_uart_preamble: raw_uart = ", raw_uart)
if raw_uart is None:
@@ -1989,154 +2090,34 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
return self._found
def check_mem_survive(self) -> Optional[CC2650Device]:
chk_mem_response = None
ack = []
ins = bytearray()
ins.append(0x0A)
ins.append(0x01) #length
ins.append(10)
ins.append(1) #length
ins.append(0xF1)
self._interface.flush_input()
# print('ins', list(ins))
try:
self.log_verbose('[CC2650]', 'check_mem_survive att_write','0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
except SerialTimeoutException:
self.log_verbose('[CC2650]', 'check_mem_survive send fail')
except SerialTimeoutException as e:
raise RecvTimeout('device CC2650 check_mem_survive timeout') from e
else:
try:
chk_mem_response = self._cc2650.recv_uart(0.001)
ack = self._cc2650.recv_uart(0.001)
except RecvTimeout:
self.log_verbose('[CC2650]', 'check_mem_survive response timeout, no memory board')
self.log_info("no memory board")
if chk_mem_response is None:
return False
# else:
# print('ack=', ack)
pack_len = chk_mem_response[0]
mem_ack = chk_mem_response[1:pack_len+1]
if mem_ack == [3]:
chk_mem_response_hex = ''.join(format(i, '02X') for i in chk_mem_response)
self.log_verbose('[CC2650]', 'check_mem_survive success', '0x'+chk_mem_response_hex)
if ack == [3]:
return True
return False
@synchronized
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
self._found = found = []
self._found_with_id = []
scan_response = None
ins = bytearray()
ins.append(0x03)
ins.append(0x01) #length
ins.append(0xF1)
self._interface.flush_input()
for _ in range(5):
try:
self.log_verbose('[CC2650]', 'scan_callback att_write','0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
except SerialTimeoutException:
self.log_verbose('[CC2650]', 'scan_callback send fail, rescan')
continue
else:
try:
scan_response = self._cc2650.recv_uart(0.01)
except RecvTimeout:
self.log_verbose('[CC2650]', 'scan_callback response timeout, no device, rescan')
continue
else:
if scan_response is None:
self.log_verbose('[CC2650]', 'scan_callback response is None, rescan')
continue
else:
break
if scan_response is None:
self.log_verbose('[CC2650]', 'scan_callback response is None--2')
return False
scan_response_hex = ''.join(format(i, '02X') for i in scan_response)
self.log_verbose('[CC2650]', 'scan_callback success', '0x'+scan_response_hex)
if len(scan_response) <= 2:
print('******************************************************************')
print('******************************************************************')
print('******************************************************************')
print('******************************************************************')
print('****need to fix, len(scan) <= 2')
print()
return False
pack_len = scan_response[0]
device_info_pkg = scan_response[1:pack_len+1]
# instruction format:
# ins[0]: get_scan_response = 0x04
# ins[1]: number of scanned device=0; a certain device = device_id (could be 1~8)
# ins[2]: addr=MAC=1, localName=2, company_code=3, version_info=4, battery_info=5, all_info=6;
# attr_length=0, e.g. len(addr)=6, len(company_code)=4
local_mac = None
local_cc = None
local_ver = None
local_bat = None
local_name = None
local_addr_type = None
# get device attribute length
attr_length = [6, 4, 6, 5, 20]
index = 0
local_mac = get_device_mac_in_address_format(device_info_pkg[index:index + 6])
index = index + 6
local_cc = get_device_company_code(device_info_pkg[index:index + 4])
index = index + 4
local_ver = device_info_pkg[index:index + 6]
index = index + 6
local_bat = get_device_battery_info(device_info_pkg[index:index + 5])
index = index + 5
local_name = get_device_name_in_string_format(list(device_info_pkg[index:index + 20]))
index = index + 20
local_addr_type = int(device_info_pkg[index:index + 1][0])
index = index + 1
response = is_headstage_device_central_version(local_mac,
local_addr_type,
local_name,
local_cc,
local_ver,
local_bat)
if response is not None:
self.log_info('found', address_str(response.mac_address), response.serial_number)
self._interface.flush_input()
# apppend into db
devicesList = DeviceAPI.getByMac(address_str(response.mac_address))
if devicesList is not None:
if len(devicesList) == 0:
DeviceAPI.create(response.device_name, local_ver, address_str(response.mac_address))
found.append(response)
# print('scan_done_found', found)
self._found_with_id.append((response, 0 + 1))
callback(response)
return True
@synchronized
def connect(self, response: DeviceResponseInfo, direct_connect: bool = False) -> Optional[CC2650Device]:
if self._handle is not None:
@@ -2146,199 +2127,225 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
addr_type = response.addr_type
address_s = cc2650.address_str(address)
self.log_info(DEVICE_CONNECTING, address_s)
connect_ins = bytearray()
connect_ins.append(5)
connect_ins.append(8) #length
connect_ins.append(addr_type)
connect_ins.append(address[0])
connect_ins.append(address[1])
connect_ins.append(address[2])
connect_ins.append(address[3])
connect_ins.append(address[4])
connect_ins.append(address[5])
connect_ins.append(0xF1)
connected = False
connect_response = None
ins = bytearray()
ins.append(0x05)
ins.append(0x08) #length
ins.append(addr_type)
ins.append(address[0])
ins.append(address[1])
ins.append(address[2])
ins.append(address[3])
ins.append(address[4])
ins.append(address[5])
ins.append(0xF1)
self._interface.flush_input()
# send connect command
if direct_connect is True:
for retry in range(5):
# send device mac and addrType
try:
self.log_verbose('[CC2650]', 'connect att_write', '0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
self._cc2650.send("bytes", bytes(connect_ins))
except RecvTimeout:
self.log_verbose('[CC2650]', 'connect send fail')
continue
except SerialTimeoutException as e:
raise RecvTimeout('device CC2650 connect fail') from e
return None
else:
# connection establish done?
for retry_recv_ack in range(10):
try:
connect_response = self._cc2650.recv_uart(2)
con_done = self._cc2650.recv_uart(timeout = 0.5)
# print("con_done = ", con_done)
except RecvTimeout:
# self.log_verbose('[CC2650]', 'connect response timeout')
if retry < 5:
self.log_verbose('[CC2650]', 'connect retry')
continue
else:
self.log_info("recv connection timeout, retry... ")
continue
# is the ack valid?
if con_done is None:
continue
elif con_done[0] is 46 and \
con_done[1] is 80 and \
con_done[2] is 48 and \
con_done[3] is 4:
connected = True
break
else:
for dev in self._found:
if dev.mac_address == address:
if connect_response is None:
self.log_verbose('[CC2650]', 'connect response timeout')
return False
# send device mac and addrType
try:
# print('send_connect',bytes(connect_ins))
self._cc2650.send("bytes", bytes(connect_ins))
pack_len = connect_response[0]
connect_ack = connect_response[1:pack_len+1]
if pack_len == 1:
if connect_ack[0] == 3:
connected = True
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
self.log_verbose('[CC2650]', 'connect success', '0x'+connect_response_hex)
except SerialTimeoutException as e:
raise RecvTimeout('device CC2650 connect fail') from e
elif pack_len == 4:
if connect_ack[0] == 46 and connect_ack[1] == 80 and \
connect_ack[2] == 48 and connect_ack[3] == 4:
connected = True
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
self.log_verbose('[CC2650]', 'connect success', '0x'+connect_response_hex)
else:
sleep(2)
if connected == True:
# CC2650Device(device_id, master, scan_response) is a slave device
# device_id is don't care, because it will be overwrite later
dont_care = 0
self._device = ret = CC2650Device(device_id=dont_care, master=self, response_info=response)
self.log_verbose('[CC2650]', DEVICE_CONNECTED, address_s)
return ret
# connection establish done?
for retry_recv_ack in range(5):
self._cc2650.send("bytes", bytes((0, 0, 0, 0)))
connect_response_hex = ''.join(format(i, '02X') for i in connect_response)
self.log_verbose('[CC2650]', 'connect fail', '0x'+connect_response_hex)
return False
try:
con_done = self._cc2650.recv_uart(timeout = 0.1)
except RecvTimeout:
self.log_info("recv connection timeout, retry... ")
continue
# is the ack valid?
if con_done is None:
continue
elif con_done[0] is 46 and \
con_done[1] is 80 and \
con_done[2] is 48 and \
con_done[3] is 4:
connected = True
# print('con_done=', con_done)
break
else:
continue
# if select device is invalid or connect failed
self._interface.flush_input()
if connected is False:
if direct_connect is True:
self.reset_internal()
self.reset_hardware()
self._interface.flush()
return None
# CC2650Device(device_id, master, scan_response) is a slave device
# device_id is don't care, because it will be overwrite later
dont_care = 0
self._device = ret = CC2650Device(device_id=dont_care, master=self, response_info=response)
self.log_info(DEVICE_CONNECTED, address_s)
sleep(0.5)
print('ret',ret)
return ret
@synchronized
def disconnect(self, device: int, force=False) -> bool:
self.log_info(DEVICE_DISCONNECTING, device)
ins = bytearray()
ins.append(0x08)
ins.append(0x01) #length
ins.append(8)
ins.append(1) #length
ins.append(0xF1)
self._interface.flush_input()
for retry in range(5):
try:
self.log_verbose('[CC2650]', 'disconnect att_write','0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
except SerialTimeoutException:
self.log_verbose('[CC2650]', 'disconnect send fail')
continue
else:
self.reset_internal()
self.reset_hardware()
self.log_verbose('[CC2650]', 'disconnect success')
return True
# try:
# disconnect_response = self._cc2650.recv_uart(0.01)
# print(disconnect_response)
# except RecvTimeout:
# self.log_verbose('[CC2650]', 'disconnect response timeout')
# if retry < 5:
# self.log_verbose('[CC2650]', 'connect retry')
# continue
# else:
# break
# if disconnect_response is None:
# return False
# pack_len = disconnect_response[0]
# disconnect_ack = disconnect_response[1:pack_len+1]
# if disconnect_ack == [3]:
# disconnect_response_hex = ''.join(format(i, '02X') for i in disconnect_response)
# self.log_verbose('[CC2650]', 'disconnect success', '0x'+disconnect_response_hex)
# self.reset_internal()
# self.reset_hardware()
# return True
self.log_verbose('[CC2650]', 'disconnect fail')
return False
@synchronized
def write_characteristic(self, device: int, handle: int, data: bytes) -> bool:
write_response = None
ins = bytearray()
ins.append(0x06)
ins.append(len(data)+2) #length = handle + C0C0XXXX(data len) + F1
ins.append(handle)
ins.extend(data)
ins.append(0xF1)
self._interface.flush_input()
try:
self.log_verbose('[CC2650]', 'write_characteristic', device, str(hex(handle).upper()))
self.log_verbose('[CC2650]', 'write_characteristic att_write','0x'+str.upper(ins.hex()))
# print('send_disconnect',bytes(ins))
self._cc2650.send("bytes", bytes(ins))
except SerialTimeoutException:
self.log_verbose('[CC2650]', 'write_characteristic send fail')
except RecvTimeout:
self.log_warn('disconnect time out')
return False
except RuntimeError as e:
self.log_warn('suppressed error', str(e))
return False
else:
try:
write_response = self._cc2650.recv_uart(0.5)
except RecvTimeout:
self.log_verbose('[CC2650]', 'write_characteristic response timeout')
if write_response is None:
self.log_verbose('[CC2650]', 'write_characteristic fail')
return False
pack_len = write_response[0]
write_ack = write_response[1:pack_len+1]
if write_ack == [3]:
write_response_hex = ''.join(format(i, '02X') for i in write_response)
self.log_verbose('[CC2650]', 'write_characteristic success', '0x'+write_response_hex)
sleep(0.01)
return True
self.log_verbose('[CC2650]', 'write_characteristic fail')
return False
finally:
self.log_info(DEVICE_DISCONNECTED, device)
# reset single 2650 after disconnected
self.reset_internal()
self.reset_hardware()
self._interface.flush()
@synchronized
def read_characteristic(self, device: int, handle: int) -> Optional[bytes]:
read_response = None
ins = bytearray()
ins.append(0x07)
ins.append(0x02) #length
# print("read_characteristic, expect_data_length = ", expect_data_length)
ret = None
ins = bytearray()
ins.append(7)
ins.append(2) #length
ins.append(handle)
ins.append(0xF1)
self._interface.flush_input()
for _ in range(2):
try:
# print('send_read',bytes(ins))
self._cc2650.send("bytes", bytes(ins))
except SerialTimeoutException:
raise RecvTimeout('device CC2650 send read_characteristic fail')
try:
ret = self._cc2650.recv_uart(timeout = 2)
except Exception as e2:
raise RecvTimeout()
else:
# print("======== read ret = ", ret)
self._interface.flush_input()
# try:
# ret = self._cc2650.recv_uart(timeout = 1)
# except Exception as e2:
# raise RecvTimeout()
# else:
# # print("read_characteristic ret = ", ret)
# pass
if ret is None:
return None
return bytes(ret)
@synchronized
def write_characteristic(self, device: int, handle: int, data: bytes):
# print("device", device)
# print("handle", handle)
# print("data", data.hex())
# self.log_info('reset')
self.log_verbose('write_characteristic', device, handle)
self.log_verbose('[CC2650]', 'att_write', str.upper(data.hex()))
ack = None
ret = None
data_array = bytearray()
data_array.append(6)
data_array.append(len(data)+2) #length
data_array.append(handle)
data_array.extend(data)
data_array.append(0xF1)
try:
self.log_verbose('[CC2650]', 'read_characteristic', device, str(hex(handle).upper()))
self.log_verbose('[CC2650]', 'read_characteristic att_write','0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
self._cc2650.send("bytes", bytes(data_array))
# print('send_write',bytes(data_array))
except SerialTimeoutException:
self.log_verbose('[CC2650]', 'read_characteristic send fail')
except SerialTimeoutException as e:
raise RecvTimeout('device CC2650 send instruction fail') from e
# read error code
try:
ret = self._cc2650.recv_uart()
# print("_______ write ack = ", ret)
except Exception as e2:
pass
else:
try:
read_response = self._cc2650.recv_uart(1)
pass
except RecvTimeout:
self.log_verbose('[CC2650]', 'read_characteristic response timeout')
if read_response is None:
return None
read_response_hex = ''.join(format(i, '02X') for i in read_response)
self.log_verbose('[CC2650]', 'read_characteristic success', '0x'+read_response_hex)
return bytes(read_response)
self._interface.flush_input()
self._interface.flush_output()
def set_notify(self, device: Union[int, Device], enable: bool):
if isinstance(device, CompletedDevice):
@@ -2439,6 +2446,7 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
self._cc2650_log_level = self.log_level
def read_characteristic(self, device: int, handle: int) -> Optional[bytes]:
self.log_verbose('read_characteristic', device, '0x%02X' % handle)
master = self._cc2650[device]
@@ -2496,6 +2504,11 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
self._interface.flush()
self._selector.select(device_id)
# self._mem_selector.select(device_id)
# print("multiMaster selector = ", device_id)
# print("\n")
# device._notify_flag = enable
try:
master.write_characteristic(device_id, self.NOTIFY_HANDLE, value)
except SendInstructionTimeoutError:
+169 -287
View File
@@ -854,8 +854,7 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
'_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop', '_show_data',
'_last_mem_wrong_information', '_last_mem_cnt', '_last_elite_notify_times')
'_mode_stop', '_show_data')
def __init__(self):
super().__init__()
@@ -872,10 +871,6 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
self._show_data = False
self._last_mem_wrong_information = -1
self._last_mem_cnt = -1
self._last_elite_notify_times = -1
@property
def name(self) -> str:
return self.NAME
@@ -889,70 +884,23 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
def decode(self, data: bytes) -> Optional[RecordingData]:
if len(data) < 18:
return None
#/* Elite Notify data:
# * +--------+----------+---------+---------+---------+-----------+-----------------+
# * | id(1B) | time(4B) | ch1(4B) | ch2(4B) | ch3(4B) | cycle(2B) | finish_flag(1B) |
# * | bat(4B) | notify#(1B) | ch4(4B) | ch5(4B) | ch6(4B) | __(3B) |
# * +---------+-------------+---------+---------+---------+--------+
# */
#/*
# * EliteADCControl(): use ADC plot, and send what data to controller
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
# * | MODE | ch1 | ch2 | ch3 | cycle | ch4 |
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
# * | CURVE_IV | Iin | Vout | Vin | | Vmon |
# * | CURVE_IV_CY | Iin | Vout | Vin | v | Vmon |
# * | CURVE_VO | Iin | Vout | Vin | | Vmon |
# * | CURVE_RT | Iin | Vout | R | | Vmon |
# * | CURVE_VT | Iin | Vin | | | |
# * | CURVE_IT | Iin | Vin | Vout | | Vmon |
# * | CURVE_CC | Iin | Vin | Vout | | Vmon |
# * | CURVE_CP | Iin | Vout-Vin | Vout | | Vmon |
# * | CURVE_CV | Iin | Vout-Vin | Vout | v | Vmon |
# * | CURVE_LSV | Iin | Vout-Vin | Vout | | Vmon |
# * | CURVE_CA | Iin | Vout-Vin | Vout | | Vmon |
# * | CURVE_OCP | Iin | Vmon-Vin | Vin | | Vmon |
# * | CURVE_UNI_PULSE | pul1_Iin | pul2_Iin | | | |
# * | CURVE_DPV | c1&c2_avg | Vout-Vin | Vout | | Vmon |
# * | CURVE_DPV_SMPRATE | Iin | Vout-Vin | Vout | | Vmon |
# * | CURVE_DPV_ADVANCE | c1&c2_avg | Vout-Vin | Vout | | Vmon |
# * | CURVE_DPV_ADVANCE_SMPRATE | Iin | Vout-Vin | Vout | | Vmon |
# * +---------------------------+-----------+-----------+-----------+-----------+-----------+
# *
# * ps. c1_avg = pul1_Iin
# * ps. c2_avg = pul2_Iin
# */
voltage = 0
mem_cnt = data[1]
time_stamp: float = struct.unpack('<I', data[1+3:5+3])[0]
ch1 = struct.unpack('<i', data[5+3:9+3])[0] # unit: nA
ch2 = struct.unpack('<i', data[9+3:13+3])[0] # unit: uV
ch3 = struct.unpack('<i', data[13+3:17+3])[0] # unit: mOm
time_stamp: float = struct.unpack('<I', data[4:8])[0] # unit: ms 0x18030000
current = struct.unpack('<i', data[8:12])[0] # unit: nA
voltage = struct.unpack('<i', data[12:16])[0] # unit: uV
impedance = struct.unpack('<i', data[16:20])[0] # unit: mOm
cycle_number = struct.unpack('<H', data[17+3:19+3])[0]
finish_mode_falg = data[19+3]
battery = struct.unpack('<i', data[20+3:24+3])[0]
elite_notify_times = data[24+3]
ch4 = struct.unpack('<i', data[25+3:29+3])[0]
ch5 = struct.unpack('<i', data[29+3:33+3])[0]
ch6 = struct.unpack('<i', data[33+3:37+3])[0]
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
if mem_wrong_information != self._last_mem_wrong_information:
print(datetime.now(), 'device', str(self.device), 'mem_wrong_information[43:47]:', data[43:47], mem_wrong_information, self._last_mem_wrong_information, flush = True)
if mem_cnt != self._last_mem_cnt+1:
if not (mem_cnt == 0 and self._last_mem_cnt == 255):
print(datetime.now(), 'device', str(self.device), 'mem_cnt:', mem_cnt, 'self._last_mem_cnt:', self._last_mem_cnt, flush = True)
if (elite_notify_times != self._last_elite_notify_times+1) and not (elite_notify_times == 0 and self._last_elite_notify_times == 0):
if not (elite_notify_times == 0 and self._last_elite_notify_times == 255):
print(datetime.now(), 'device', str(self.device), 'elite_notify_times:', elite_notify_times, 'self._elite_notify_times:', self._last_elite_notify_times, flush = True)
self._last_mem_wrong_information = mem_wrong_information
self._last_mem_cnt = mem_cnt
self._last_elite_notify_times = elite_notify_times
ram_num = data[47]
broken_flag = data[-1]
@@ -976,29 +924,25 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
else:
if self._show_data:
print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
'|', ch1, '|', ch2, '|', ch3, '|', cycle_number,
'|', ch4, '|', ch5, '|', ch6,
'|', finishMode, '@', str(self.device), flush = True)
'|', current, '|', voltage, '|', impedance, '|', cycle_number,
'|', notify_one, '|', notify_two, '|', notify_three,
'|', finishMode, '@', str(self.device))
# print('|', '{:10}'.format(time_stamp),
# '|', '{:4}'.format(delta),
# '|', '{:10}'.format(int(time_stamp * 1000 / 2)), #[usec]
# '|', '{:10}'.format(ch1), #[nA]
# '|', '{:10}'.format(ch2), #[uV]
# '|', '{:10}'.format(ch3),
# '|', '{:5}'.format(cycle_number),
# '|', '{:10}'.format(ch4), #Voutin[uV]
# '|', '{:10}'.format(ch5),
# '|', '{:10}'.format(ch6),
# '|', '{:5}'.format(battery), #[mV]
# '|', '{:4}'.format(elite_notify_times),
# '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|', flush = True)
# print('|', '{:10}'.format(time_stamp),
# '|', '{:4}'.format(delta),
# '|', '{:10}'.format(int(time_stamp * 1000 / 2)),
# '|', '{:10}'.format(current),
# '|', '{:10}'.format(voltage),
# '|', '{:10}'.format(impedance),
# '|', '{:5}'.format(cycle_number),
# '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|')
# print('|', '{:5}'.format(mem_wrong_information),
# '|', '{:2}'.format(ram_num),
# '|', '{:2}'.format(broken_flag),
# '@', str(self.device), '|')
# print('|', '{:5}'.format(mem_wrong_information),
# '|', '{:2}'.format(ram_num),
# '|', '{:2}'.format(broken_flag),
# '@', str(self.device), '|')
pass
if finishMode == True:
print("finishMode full data:", list(data), datetime.now())
@@ -1007,13 +951,13 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
self._mode_stop = 0
ret = RecordingData(self.device, int(time_stamp * 1000 / 2), 0)
ret.append_data(0, ch1)
ret.append_data(1, ch2)
ret.append_data(2, ch3)
ret.append_data(0, current)
ret.append_data(1, voltage)
ret.append_data(2, impedance)
ret.append_data(3, cycle_number)
ret.append_data(4, ch4)
ret.append_data(5, ch5)
ret.append_data(6, ch6)
ret.append_data(4, 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)
@@ -1401,8 +1345,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_package', 'cali_coeff', '_ac_amp', '_mode',
'_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff',
'cali_coeff', '_ac_amp', '_mode',
'_last_phase', '_first_phase_flag', '_show_data')
def __init__(self, cali_coeff: bytes = None):
@@ -1420,230 +1364,139 @@ class EISZeroOneDataDecoder(RecDataDecoder):
self._last_phase = 0
self._first_phase_flag = 1
self._cali_package: Optional[bytes] = None
self._cali_coeff: Optional[bytes] = None
self.cali_coeff: Optional[List[Tuple[int, int]]] = None
self._show_data = False
if self._cali_package is None:
self._cali_package = cali_coeff
self.cali_coeff = self._decode_cali_coeff(self._cali_package)
if cali_coeff is not None:
self._cali_coeff = cali_coeff
self.cali_coeff = self._decode_cali_coeff(cali_coeff)
@staticmethod
def _decode_cali_coeff(cali_coeff: bytes) -> Optional[List[Tuple[int, int]]]:
if cali_coeff != b'':
cis_data_len = 20
cali_table = []
hsrtia_a = []
hsrtia_b = []
rolloff = []
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([8, 4], dtype = int)
phase_offset = numpy.zeros([8, 4], dtype = int)
phase_coeff = numpy.zeros([4, 4], dtype = int)
phase_offset = numpy.zeros([4, 4], dtype = int)
########################################
# phase_coeff
# [[freq0, freq1, freq2, freq3] ----->gain0
# [freq0, freq1, freq2, freq3] ----->gain1
# [freq0, freq1, freq2, freq3] ----->gain2
# [freq0, freq1, freq2, freq3] ----->gain3
# [[gain0, g1, g2, g3] ----->最高頻
# [gain0, g1, g2, g3] ----->中頻
# [gain0, g1, g2, g3] ----->低頻
# [gain0, g1, g2, g3] ----->最低頻
# ]
#######################################
#hstia=0
cis_cali_packet = 1
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
# print('cali_coeff', cali_coeff)
cutoff_freq = struct.unpack('>I', cali_coeff[1:5])[0] * 100 #4
# temp = struct.unpack('>B', cali_coeff[5:6])[0] #1
# hsrtia_200r = struct.unpack('>B', cali_coeff[6:7])[0] #1
# hsrtia_5k = struct.unpack('>H', cali_coeff[7:9])[0] #2
# hsrtia_20k = struct.unpack('>H', cali_coeff[6:8])[0] #2
# hsrtia_160k = struct.unpack('>I', cali_coeff[8:12])[0] #4
cis_cali_packet = 2
index = (cis_cali_packet - 1) * cis_data_len
index = 20
g = 0
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
cis_cali_packet = 3
index = (cis_cali_packet - 1) * cis_data_len
index = 40
g = 0
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
#hstia=1
cis_cali_packet = 4
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
#Lv[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])
cis_cali_packet = 5
index = (cis_cali_packet - 1) * cis_data_len
#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])
#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])
#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])
index = 140
g = 1
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
cis_cali_packet = 6
index = (cis_cali_packet - 1) * cis_data_len
index = 160
g = 1
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
#hstia=2
cis_cali_packet = 7
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 8
index = (cis_cali_packet - 1) * cis_data_len
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[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
cis_cali_packet = 9
index = (cis_cali_packet - 1) * cis_data_len
index = 200
g = 2
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
#hstia=3
cis_cali_packet = 10
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 11
index = (cis_cali_packet - 1) * cis_data_len
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[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
cis_cali_packet = 12
index = (cis_cali_packet - 1) * cis_data_len
index = 240
g = 3
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
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]
#hstia=4
cis_cali_packet = 13
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 14
index = (cis_cali_packet - 1) * cis_data_len
g = 4
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
cis_cali_packet = 15
index = (cis_cali_packet - 1) * cis_data_len
g = 4
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
#hstia=5
cis_cali_packet = 16
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 17
index = (cis_cali_packet - 1) * cis_data_len
g = 5
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
cis_cali_packet = 18
index = (cis_cali_packet - 1) * cis_data_len
g = 5
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
#hstia=6
cis_cali_packet = 19
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 20
index = (cis_cali_packet - 1) * cis_data_len
g = 6
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
cis_cali_packet = 21
index = (cis_cali_packet - 1) * cis_data_len
g = 6
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
#hstia=7
cis_cali_packet = 22
index = (cis_cali_packet - 1) * cis_data_len
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+2:index+6])[0])
hsrtia_b.append(struct.unpack('>q', cali_coeff[index+6:index+14])[0])
rolloff.append(struct.unpack('>i', cali_coeff[index+14:index+18])[0])
cis_cali_packet = 23
index = (cis_cali_packet - 1) * cis_data_len
g = 7
phase_coeff[g][0] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][0] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][1] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][1] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
cis_cali_packet = 24
index = (cis_cali_packet - 1) * cis_data_len
g = 7
phase_coeff[g][2] = struct.unpack('>i', cali_coeff[index+2:index+6])[0]
phase_offset[g][2] = struct.unpack('>i', cali_coeff[index+6:index+10])[0]
phase_coeff[g][3] = struct.unpack('>i', cali_coeff[index+10:index+14])[0]
phase_offset[g][3] = struct.unpack('>i', cali_coeff[index+14:index+18])[0]
print('cutoff_freq', cutoff_freq)
print('hsrtia_a', hsrtia_a)
print('hsrtia_b', hsrtia_b)
print('rolloff', rolloff)
print('hsrtia_c', hsrtia_c)
print('phase_coeff')
print(phase_coeff)
print('phase_offset')
print(phase_offset)
cali_table.append((phase_coeff, phase_offset, hsrtia_a, hsrtia_b, rolloff))
cali_table.append((cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d))
return cali_table
else:
@@ -1652,10 +1505,10 @@ class EISZeroOneDataDecoder(RecDataDecoder):
@property
def name(self) -> AnyStr:
if self._cali_package is None:
if self._cali_coeff is None:
return self.NAME
else:
return self.NAME.encode() + b':' + self._cali_package
return self.NAME.encode() + b':' + self._cali_coeff
def message(self) -> Optional[str]:
ret = self._message
@@ -1700,8 +1553,9 @@ class EISZeroOneDataDecoder(RecDataDecoder):
if self.cali_coeff is not None and (self._mode == 0 or self._mode == 5):
hsrtia_a = []
hsrtia_b = []
rolloff = []
phase_coeff, phase_offset, hsrtia_a, hsrtia_b, rolloff = self.cali_coeff[0]
hsrtia_c = []
hsrtia_d = []
cutoff_freq, phase_coeff, phase_offset, hsrtia_a, hsrtia_b, hsrtia_c, hsrtia_d = self.cali_coeff[0]
if (self._mode == 0 or self._mode == 5):
img = ch1
@@ -1709,11 +1563,19 @@ class EISZeroOneDataDecoder(RecDataDecoder):
freq = ch3
fre_idx = 0
voltage_amp = round(ch4 / 1000) # Amp[mV]
rolloff_cali = rolloff[gain]
# 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)
current = (voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain]) / 1e8 #[nA]
# 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]
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
@@ -1735,8 +1597,20 @@ class EISZeroOneDataDecoder(RecDataDecoder):
phase = raw_phase - ideal_raw_phase
phase = phase % 180 if phase % 180<=90 else phase % 180-180
imag_after_cal = round(impedance * math.sin(phase * math.pi / 180))
real_after_cal = round(impedance * math.cos(phase * math.pi / 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(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(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):
@@ -1782,13 +1656,13 @@ 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:
if self._mode == 0 or self._mode == 5: #EIS Mode
ret.append_data(0, ch1) #raw_img
ret.append_data(1, ch2) #raw_real
ret.append_data(2, ch3 * 10) #Frequency [mHz]
ret.append_data(3, cycle_number) #cycle
ret.append_data(4, imag_after_cal) #Z_imag [Ohm]
ret.append_data(5, real_after_cal) #Z_real [Ohm]
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(8, round(current)) #Current [nA]
@@ -1800,7 +1674,15 @@ class EISZeroOneDataDecoder(RecDataDecoder):
ret.append_data(12, notify_three)
ret.append_data(13, voltage_amp) #amp[mV]
else: #CV Mode
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
ret.append_data(0, ch1) #Iin [nA]
ret.append_data(1, ch2) #Vset [nV]
ret.append_data(2, ch3) #Vout [nV]
-1
View File
@@ -794,7 +794,6 @@ class InstructionDataContent(InstructionContent):
offset += 1
else:
buffer.extend([0]*(self._width.size-len(buffer)))
for i in range(self._width.size):
if self._width.little_endian:
value |= (buffer[offset] << (1 * i))
+17
View File
@@ -1292,6 +1292,9 @@ 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
@@ -1403,6 +1406,20 @@ class DebugDevice(CompletedDevice):
def read_command_return_data(self) -> Optional[bytes]:
return None
def send_command(self, ins_type: int, ins_oper: int, *instruction: int):
length = len(instruction)
print('instruction send :',
'%02X' % ((ins_type & 0xF0) | (self.device_id & 0x0F)),
'%02X' % ((ins_oper & 0xF0) | (length & 0x0F)),
' '.join(map(lambda v: '%02X' % v, instruction)))
def send_instruction(self, ins_type: int, ins_oper: int, *instruction: int):
length = len(instruction)
print('instruction send :',
'%02X' % ((ins_type & 0xF0) | (self.device_id & 0x0F)),
'%02X' % ((ins_oper & 0xF0) | (length & 0x0F)),
' '.join(map(lambda v: '%02X' % v, instruction)))
@property
def battery(self) -> int:
return 100
+10 -14
View File
@@ -3697,6 +3697,7 @@ class CC2650Central(LoggerFlag):
def recv(self, timeout: Optional[float] = None) -> Optional[list]:
packet = self._recv_byte()
# print("packet = ", packet)
if packet is None:
return None
@@ -3708,8 +3709,6 @@ class CC2650Central(LoggerFlag):
def _recv_byte(self) -> Optional[int]:
ret = self._recv_bytes(1)
# if ret is not None:
# print('packet = {0}'.format(hex(ret[0]).upper()))
return ret[0] if ret is not None else None
def _recv_bytes(self, size: int = 1) -> Union[None, bytes]:
@@ -3725,28 +3724,27 @@ class CC2650Central(LoggerFlag):
return None
def _recv_event(self, timeout: Optional[float] = 1) -> Optional[list]:
packet = self._recv_byte()
code = self._recv_byte()
# print("code = ", code)
if packet is None:
if code is None:
return None
length = self._recv_byte()
len_b = _struct.pack("B", length)
data = b''
# print('code::',code,'length::',length)
_start = _time()
data = b''
while len(data) < length:
packets = self._recv_bytes(length - len(data))
# hex_packets = ''.join(format(i, '02x') for i in packets)
# print("packets = ", hex_packets.upper())
ret = self._recv_bytes(length - len(data))
# print("ret = ", ret)
if packets is not None:
data += packets
if ret is not None:
data += ret
elif timeout is not None and _time() - _start > timeout:
raise RecvTimeout()
data = len_b + data
self._interface.flush()
return list(data)
@@ -3762,7 +3760,5 @@ class CC2650Central(LoggerFlag):
raise RecvTimeout()
else:
uart_data_hex = ''.join(format(i, '02X') for i in uart_data)
# print('uart_data: 0x{0}'.format(uart_data_hex.upper()))
return uart_data
+19 -34
View File
@@ -13,7 +13,7 @@ MSM_REG_WRITE = 0x01
MEM_INS_WRITE = 0x02
MEM_INS_READ = 0x03
MEM_REG_READ = 0x05
DEFAULT_REGISTER_VALUE = 0b0100_0001 # 0x41
DEFAULT_REGISTER_VALUE = 0b0100_0011 # 67
MEM_SIZE = 0x1000
_SLEEP_TIME_ = 0.001
@@ -457,16 +457,6 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
self._spi.send_byte(tx)
def test_ram(self, channel: int):
spi_MOSI = [MEM_INS_WRITE, 0, 0, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
self._spi.send_byte(spi_MOSI)
print('device:', channel, 'spi_MOSI:',spi_MOSI)
spi_MISO = [0] * len(spi_MOSI)
spi_MISO[0:3] = [MEM_INS_READ, 0, 0]
spi_MISO = self._spi.send_byte(spi_MISO)
print('device:', channel, 'spi_MISO:', spi_MISO)
class ExtMemManager:
def __init__(self, ext_mem: MultiExtMemSpiInterface):
self._ext_mem = ext_mem
@@ -503,31 +493,28 @@ class ExtMemManager:
ret[channel] = tuple(r)
print('ret=', ret)
return ret
@staticmethod
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]], channel: int) -> int:
def is_no_device(result: Tuple[Optional[int], Optional[int]]) -> bool:
r1, r2 = result
r1_check = False
r2_check = False
return (r1 is None or r2 is None) and (r1 is None or r1 == 0) and (r2 is None or r2 == 0)
if r1 is not None and r1 != 0:
if (r1 & 0b11000001 == DEFAULT_REGISTER_VALUE & 0b11000001):
r1_check = True
print('device:', channel, 'ram0 ready')
if r2 is not None and r2 != 0:
if (r2 & 0b11000001 == DEFAULT_REGISTER_VALUE & 0b11000001):
r2_check = True
print('device:', channel, 'ram1 ready')
print('--------------------')
@staticmethod
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]]) -> int:
r1, r2 = result
if r1_check and r2_check:
return 0
else:
if r1 is None or r2 is None:
return 1
if r1 is not None and r1 > 0 and r1 != DEFAULT_REGISTER_VALUE:
return 2
if r2 is not None and r2 > 0 and r2 != DEFAULT_REGISTER_VALUE:
return 3
return 0
def get_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
if result is None:
result = self.get_ext_mem_register()
@@ -535,14 +522,12 @@ class ExtMemManager:
ret = []
for channel, result in enumerate(result):
if self.is_memory_test_fail(result, channel) != 0:
if self.is_no_device(result):
continue
if self.is_memory_test_fail(result) != 0:
continue
ret.append(channel)
# test ram
# for channel in self._ext_mem.foreach():
# if channel == 4 or channel == 5:
# self._ext_mem.test_ram(channel)
return ret
-2
View File
@@ -53,8 +53,6 @@ class UARTInterface(LowLevelHardwareInterface):
:param data: raw byte instruction
:raises SerialTimeoutException:
"""
data_hex = ''.join(format(i, '02X') for i in data)
# print('send_byte: 0x{0}'.format(data_hex.upper()))
self._serial.write(data)
def recv_byte(self, size: int) -> Optional[bytes]:
+26 -1
View File
@@ -49,6 +49,9 @@ class Project(threading.Thread):
self._count = 1 #流水號
self._project_meta_id = -1
self._subject = []
self.log_verbose = log_verbose
self._logger = logging.getLogger('project')
self._logger.setLevel('DEBUG')
@@ -69,7 +72,10 @@ class Project(threading.Thread):
collection = Collection.find_collection(default_name, default_parent)
parent = {"folder": [collection.id]}
# create project folder
collection = Collection.create_collection(self.name, parent)
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):
@@ -101,6 +107,22 @@ 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:
@@ -278,6 +300,9 @@ class Project(threading.Thread):
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
+1 -1
View File
@@ -175,7 +175,7 @@ class TaskManager():
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]})
collection = Collection.create_collection(task.name, {"folder": [parent.id]}, False)
task.parent = {"folder": [collection.id]}
else:
task.parent = {"folder": [parent.id]}
+99 -29
View File
@@ -35,8 +35,11 @@ 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.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
_RUNTIME_COMPILE = False
@@ -329,6 +332,18 @@ 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()
@@ -558,8 +573,15 @@ 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'''
@@ -863,32 +885,20 @@ class ControlServer(SocketServer, ControlServerAPI):
@logging_info
def device_update_calibration(self, device: int) -> Union[bool, str]:
connect_device = self.device_manager.get_device(device)
if connect_device == None:
return
mac_address = address_str(connect_device.mac_address)
device = Device.get_device({"mac_address": mac_address})
mac_address = connect_device.mac_address
try:
if connect_device.library.name.startswith('Elite_EIS'):
# update calibration version
connect_device._device.update_cali_version()
# check if is first time or calibration version is different
if connect_device._device._cali_version == -1 or (device.calibration_version != connect_device._device._cali_version):
# get calibration info from device
connect_device.calibration_info('EISZeroOne')
# update_calibration_info
Device.update_device(
{ "mac_address": mac_address },
{
'calibration': connect_device.calibration ,
'calibration_version': connect_device._device._cali_version
}
)
else:
connect_device._device._coeff = device.calibration
if connect_device.library.name.startswith('Neulive3.'):
connect_device.calibration_info('NeuliveThreeOne')
elif connect_device.library.name.startswith('Neulive'):
connect_device.calibration_info('TDC4VC')
elif connect_device.library.name.startswith('EliteEIS'):
connect_device.calibration_info('EISZeroOne')
except BaseException as e:
# reset device info in db
DeviceAPI.updateByMac(
mac_address,
address_str(mac_address),
{
'connect_id': -1,
'connect_status': 'idle',
@@ -900,6 +910,14 @@ class ControlServer(SocketServer, ControlServerAPI):
print(e)
return False
else:
# update_calibration_info
DeviceAPI.updateByMac(
address_str(mac_address),
{
'calibration': str(connect_device.calibration)
}
)
# DeviceAPI.updateByAttrs('connect_status', 'update', {"connect_status": 'connect'})
return True
@logging_info
@@ -1107,7 +1125,7 @@ class ControlServer(SocketServer, ControlServerAPI):
client = self.data_server.client()
project = None
project_meta_id = None
_project_meta_id = None
if client is not None:
info = self.file_manager.use(device)
@@ -1121,10 +1139,12 @@ class ControlServer(SocketServer, ControlServerAPI):
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)
_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, _project_meta_id)
def _device_set_disable_cache(self, device: CompletedDevice, disable):
if disable:
@@ -1354,6 +1374,57 @@ 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:
@@ -1398,7 +1469,6 @@ class ControlServer(SocketServer, ControlServerAPI):
if client is not None:
with client:
client.show_data(device)
class _RandomCrashThread(ServerThread):
def __init__(self):
super().__init__('Crash')
+3 -1
View File
@@ -170,9 +170,11 @@ class MqttThread(threading.Thread):
self.sleep(3)
self._mqtt_client_local.reconnect()
def publish(self, topic: str, payload: str, inter = False, qos = 2):
def publish(self, topic: str, payload: str, inter = False, analysis=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:
File diff suppressed because it is too large Load Diff
@@ -6,7 +6,7 @@
"major_product_number": 0,
"minor_product_number": 3,
"major_version_number": 1,
"minor_version_number": 1
"minor_version_number": 0
},
"constant": {
"TIME_MAX": 100000,
@@ -780,7 +780,7 @@
"expression": "VALUE"
}
},
"CA_VOLT": {
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
@@ -1301,7 +1301,7 @@
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "CA_VOLT",
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -33,7 +33,6 @@
0,
1,
1,
1,
1
],
"domain": {
@@ -618,8 +617,7 @@
"Open Circuit Potential",
"Pulse Sensing",
"Differential Pulse Voltammetry (DPV)",
"Chronopotentiometry",
"Idle"
"Chronopotentiometry"
]
},
"VOLT_ORIGIN": {
@@ -820,7 +818,7 @@
"expression": "VALUE"
}
},
"CA_VOLT": {
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
@@ -951,7 +949,6 @@
"10": "cali_dac_test",
"11": "cali_adc_test",
"12": "",
"17": "idle",
"*": "start_data"
}
}
@@ -979,9 +976,6 @@
"VIS_STI",
"_cdr('1X;4X>ADC_VALUE_I')"
],
"idle": [
"_idle()"
],
"start_data": [
"data_format",
"_notify(True)",
@@ -1029,7 +1023,7 @@
"6": "const_current",
"7": "curve_cv3",
"8": "curve_lsv",
"9": "curve_ca",
"9": "curve_const_vscan",
"13": "curve_ocp",
"14": "curve_pulse_sensing",
"15": "curve_dpv",
@@ -1366,10 +1360,10 @@
"2B>pe"
]
},
"curve_ca": {
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "CA_VOLT",
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -1,12 +1,12 @@
{
"name": "Elite_EDC_1.5re",
"name": "Elite_EDC_1.5r2",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite.*",
"major_product_number": 0,
"minor_product_number": 2,
"major_version_number": 1,
"minor_version_number": 7
"minor_version_number": 8
},
"constant": {
"TIME_MAX": 100000,
@@ -33,7 +33,6 @@
0,
1,
1,
1,
1
],
"domain": {
@@ -618,8 +617,7 @@
"Open Circuit Potential",
"Pulse Sensing",
"Differential Pulse Voltammetry (DPV)",
"Chronopotentiometry",
"Idle"
"Chronopotentiometry"
]
},
"VOLT_ORIGIN": {
@@ -820,7 +818,7 @@
"expression": "VALUE"
}
},
"CA_VOLT": {
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
@@ -951,7 +949,6 @@
"10": "cali_dac_test",
"11": "cali_adc_test",
"12": "",
"17": "idle",
"*": "start_data"
}
}
@@ -979,9 +976,6 @@
"VIS_STI",
"_cdr('1X;4X>ADC_VALUE_I')"
],
"idle": [
"_idle()"
],
"start_data": [
"data_format",
"_notify(True)",
@@ -1029,7 +1023,7 @@
"6": "const_current",
"7": "curve_cv3",
"8": "curve_lsv",
"9": "curve_ca",
"9": "curve_const_vscan",
"13": "curve_ocp",
"14": "curve_pulse_sensing",
"15": "curve_dpv",
@@ -1366,10 +1360,10 @@
"2B>pe"
]
},
"curve_ca": {
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "CA_VOLT",
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -820,7 +820,7 @@
"expression": "VALUE"
}
},
"CA_VOLT": {
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
@@ -1029,7 +1029,7 @@
"6": "const_current",
"7": "curve_cv3",
"8": "curve_lsv",
"9": "curve_ca",
"9": "curve_const_vscan",
"13": "curve_ocp",
"14": "curve_pulse_sensing",
"15": "curve_dpv",
@@ -1366,10 +1366,10 @@
"2B>pe"
]
},
"curve_ca": {
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "CA_VOLT",
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pc": "DAC_LEVEL_V_OUT_15",
@@ -34,7 +34,6 @@
0,
1,
1,
1,
1
],
"domain": {
@@ -99,24 +98,19 @@
"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": 8,
"initial": 4,
"value": [
0,
1,
2,
3,
4,
5,
6,
7,
8
4
],
"on_change": "set_general_hs_rtia"
},
@@ -147,7 +141,7 @@
"EIS_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -219,7 +213,7 @@
"CF_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -376,14 +370,10 @@
{
"expression": "MODE",
"when": {
"7": "idle",
"*": "start_data"
}
}
],
"idle": [
"_idle()"
],
"start_data": [
"data_format_cali",
"_notify(True)",
@@ -106,17 +106,13 @@
"GENERAL_HS_RTIA": {
"description": "High speed rtia gain",
"record_meta": true,
"initial": 8,
"initial": 4,
"value": [
0,
1,
2,
3,
4,
5,
6,
7,
8
4
],
"on_change": "set_general_hs_rtia"
},
@@ -147,7 +143,7 @@
"EIS_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -219,7 +215,7 @@
"CF_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -106,17 +106,13 @@
"GENERAL_HS_RTIA": {
"description": "High speed rtia gain",
"record_meta": true,
"initial": 8,
"initial": 4,
"value": [
0,
1,
2,
3,
4,
5,
6,
7,
8
4
],
"on_change": "set_general_hs_rtia"
},
@@ -147,7 +143,7 @@
"EIS_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -219,7 +215,7 @@
"CF_AC_AMP": {
"description": "AC Amplitude",
"record_meta": true,
"initial": 26,
"initial": 25,
"domain": [
2048
]
@@ -2,196 +2,16 @@
"name": "Elite_TRIG_0.1",
"version": "1.2.30",
"match_rule": {
"local_name_pattern": "Elite.*",
"local_name_pattern": "Trigger.*",
"major_product_number": 0,
"minor_product_number": 5,
"major_version_number": 1,
"minor_version_number": 0
},
"constant": {
"TIME_MAX": 100000,
"BLE_WRITE_MAX": 255,
"MODE_ALL_OUTPUT": 15,
"ELITE_CH_PR0": 0,
"ELITE_CH_D0": 1,
"ELITE_CH_A0": 2,
"ELITE_CH_A2": 3,
"ELITE_CH_A3": 4,
"ELITE_CH_A1": 5,
"ELITE_CH_D1": 6,
"ELITE_CH_PR1": 7,
"PR0": 0,
"PR1": 1,
"D0": 2,
"D1": 3,
"A0": 4,
"A1": 5,
"A2": 6,
"A3": 7
"TIME_MAX": 100000
},
"parameters": {
"USED": {
"initial": [true, true, true, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"T_EARLY": {
"initial": [5000, 5000, 5000, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"V_EARLY": {
"initial": [true, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"CYCLE": {
"initial": [10, 10, 10, 1, 1, 1, 1, 1],
"domain": {
"list": [
0, 65535
]
},
"value": "VALUE"
},
"T_MID0": {
"initial": [30000, 30000, 30000, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"T_MID1": {
"initial": [30000, 30000, 30000, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"T_MID2": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"T_MID3": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"V_MID0": {
"initial": [true, true, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"V_MID1": {
"initial": [false, false, true, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"V_MID2": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"V_MID3": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"T_LATE": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"V_LATE": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"CURRENT": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 50000
]
},
"value": "VALUE"
},
"OUTPUT_5V": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
"list": [
"BLE_WRITE_MAX"
]
},
"initial": "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]",
"value": "VALUE"
},
"BLE_READ": {
"description": "receive msg from elite",
"domain": "int"
},
"TIME_DURATION": {
"description": "timer",
"record_meta": true,
@@ -332,16 +152,15 @@
"MODE": {
"description": "working mode",
"record_meta": true,
"initial": 3,
"value": [
"Analog Current Control (ACC)",
"Idle",
"Dev Mode",
"Protocal 1",
"Protocal 2",
"Trigger"
"Analog Current Control (ACC)"
]
},
"CHANNEL": {
"description": "delete it",
"record_meta": true,
@@ -400,10 +219,7 @@
{
"expression": "MODE",
"when": {
"0": "curve_acc",
"3": "trig_timer_mode",
"4": "trig_timer_mode",
"5": "trig_timer_mode"
"0": "curve_acc"
}
},
"_sync(True)",
@@ -428,21 +244,6 @@
"CIS_VOLT",
"_cdr('20X>ADC_VALUE_I')"
],
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"
],
"ble_write": {
"type": "RIS",
"data": [
"XFF;",
"1B>BLE_WRITE[0];1B>BLE_WRITE[1];1B>BLE_WRITE[2];1B>BLE_WRITE[3];",
"1B>BLE_WRITE[4];1B>BLE_WRITE[5];1B>BLE_WRITE[6];1B>BLE_WRITE[7];",
"1B>BLE_WRITE[8];1B>BLE_WRITE[9];1B>BLE_WRITE[10];1B>BLE_WRITE[11];",
"1B>BLE_WRITE[12];1B>BLE_WRITE[13];1B>BLE_WRITE[14];1B>BLE_WRITE[15];",
"1B>BLE_WRITE[16];"
]
},
"curve_acc": {
"type": "RIS",
"parameter": {
@@ -505,677 +306,6 @@
"data": [
"XE2;X02;X03;2B>ACC_a_out3_current;1B>ACC_a_out3"
]
},
"trig_timer_mode": [
"trig_timer_mode_set_mode",
{
"expression": "USED[PR0]",
"when": {
"True": "trig_timer_mode_set_PR0"
}
},
{
"expression": "USED[PR1]",
"when": {
"True": "trig_timer_mode_set_PR1"
}
},
{
"expression": "USED[D0]",
"when": {
"True": "trig_timer_mode_set_D0"
}
},
{
"expression": "USED[D1]",
"when": {
"True": "trig_timer_mode_set_D1"
}
},
{
"expression": "USED[A0]",
"when": {
"True": "trig_timer_mode_set_A0"
}
},
{
"expression": "USED[A1]",
"when": {
"True": "trig_timer_mode_set_A1"
}
},
{
"expression": "USED[A2]",
"when": {
"True": "trig_timer_mode_set_A2"
}
},
{
"expression": "USED[A3]",
"when": {
"True": "trig_timer_mode_set_A3"
}
}
],
"trig_timer_mode_set_mode": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT"
},
"data": [
"1B>mode;",
"1XFF;"
]
},
"trig_timer_mode_set_PR0": [
"trig_timer_mode_set_PR0_para1",
"trig_timer_mode_set_PR0_para2",
"trig_timer_mode_set_PR0_para3"
],
"trig_timer_mode_set_PR0_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR0",
"para_sequence": 1,
"used": "USED[PR0]",
"v_early": "V_EARLY[PR0]",
"v_late": "V_LATE[PR0]",
"v_mid0": "V_MID0[PR0]",
"v_mid1": "V_MID1[PR0]",
"v_mid2": "V_MID2[PR0]",
"v_mid3": "V_MID3[PR0]",
"cycle": "CYCLE[PR0]",
"t_early": "T_EARLY[PR0]",
"t_late": "T_LATE[PR0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_PR0_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR0",
"para_sequence": 2,
"t_mid0": "T_MID0[PR0]",
"t_mid1": "T_MID1[PR0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_PR0_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR0",
"para_sequence": 3,
"t_mid2": "T_MID2[PR0]",
"t_mid3": "T_MID3[PR0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_PR1": [
"trig_timer_mode_set_PR1_para1",
"trig_timer_mode_set_PR1_para2",
"trig_timer_mode_set_PR1_para3"
],
"trig_timer_mode_set_PR1_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR1",
"para_sequence": 1,
"used": "USED[PR1]",
"v_early": "V_EARLY[PR1]",
"v_late": "V_LATE[PR1]",
"v_mid0": "V_MID0[PR1]",
"v_mid1": "V_MID1[PR1]",
"v_mid2": "V_MID2[PR1]",
"v_mid3": "V_MID3[PR1]",
"cycle": "CYCLE[PR1]",
"t_early": "T_EARLY[PR1]",
"t_late": "T_LATE[PR1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_PR1_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR1",
"para_sequence": 2,
"t_mid0": "T_MID0[PR1]",
"t_mid1": "T_MID1[PR1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_PR1_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_PR1",
"para_sequence": 3,
"t_mid2": "T_MID2[PR1]",
"t_mid3": "T_MID3[PR1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_D0": [
"trig_timer_mode_set_D0_para1",
"trig_timer_mode_set_D0_para2",
"trig_timer_mode_set_D0_para3",
"trig_timer_mode_set_D0_para4"
],
"trig_timer_mode_set_D0_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D0",
"para_sequence": 1,
"used": "USED[D0]",
"v_early": "V_EARLY[D0]",
"v_late": "V_LATE[D0]",
"v_mid0": "V_MID0[D0]",
"v_mid1": "V_MID1[D0]",
"v_mid2": "V_MID2[D0]",
"v_mid3": "V_MID3[D0]",
"cycle": "CYCLE[D0]",
"t_early": "T_EARLY[D0]",
"t_late": "T_LATE[D0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_D0_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D0",
"para_sequence": 2,
"t_mid0": "T_MID0[D0]",
"t_mid1": "T_MID1[D0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_D0_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D0",
"para_sequence": 3,
"t_mid2": "T_MID2[D0]",
"t_mid3": "T_MID3[D0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_D0_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D0",
"para_sequence": 4,
"d0_as_5v_en": "OUTPUT_5V[D0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"1B>d0_as_5v_en;"
]
},
"trig_timer_mode_set_D1": [
"trig_timer_mode_set_D1_para1",
"trig_timer_mode_set_D1_para2",
"trig_timer_mode_set_D1_para3",
"trig_timer_mode_set_D1_para4"
],
"trig_timer_mode_set_D1_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D1",
"para_sequence": 1,
"used": "USED[D1]",
"v_early": "V_EARLY[D1]",
"v_late": "V_LATE[D1]",
"v_mid0": "V_MID0[D1]",
"v_mid1": "V_MID1[D1]",
"v_mid2": "V_MID2[D1]",
"v_mid3": "V_MID3[D1]",
"cycle": "CYCLE[D1]",
"t_early": "T_EARLY[D1]",
"t_late": "T_LATE[D1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_D1_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D1",
"para_sequence": 2,
"t_mid0": "T_MID0[D1]",
"t_mid1": "T_MID1[D1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_D1_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D1",
"para_sequence": 3,
"t_mid2": "T_MID2[D1]",
"t_mid3": "T_MID3[D1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_D1_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_D1",
"para_sequence": 4,
"d0_as_5v_en": "OUTPUT_5V[D1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"1B>d0_as_5v_en;"
]
},
"trig_timer_mode_set_A0": [
"trig_timer_mode_set_A0_para1",
"trig_timer_mode_set_A0_para2",
"trig_timer_mode_set_A0_para3",
"trig_timer_mode_set_A0_para4"
],
"trig_timer_mode_set_A0_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A0",
"para_sequence": 1,
"used": "USED[A0]",
"v_early": "V_EARLY[A0]",
"v_late": "V_LATE[A0]",
"v_mid0": "V_MID0[A0]",
"v_mid1": "V_MID1[A0]",
"v_mid2": "V_MID2[A0]",
"v_mid3": "V_MID3[A0]",
"cycle": "CYCLE[A0]",
"t_early": "T_EARLY[A0]",
"t_late": "T_LATE[A0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_A0_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A0",
"para_sequence": 2,
"t_mid0": "T_MID0[A0]",
"t_mid1": "T_MID1[A0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_A0_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A0",
"para_sequence": 3,
"t_mid2": "T_MID2[A0]",
"t_mid3": "T_MID3[A0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_A0_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A0",
"para_sequence": 4,
"current": "CURRENT[A0]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"2B>current;"
]
},
"trig_timer_mode_set_A1": [
"trig_timer_mode_set_A1_para1",
"trig_timer_mode_set_A1_para2",
"trig_timer_mode_set_A1_para3",
"trig_timer_mode_set_A1_para4"
],
"trig_timer_mode_set_A1_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A1",
"para_sequence": 1,
"used": "USED[A1]",
"v_early": "V_EARLY[A1]",
"v_late": "V_LATE[A1]",
"v_mid0": "V_MID0[A1]",
"v_mid1": "V_MID1[A1]",
"v_mid2": "V_MID2[A1]",
"v_mid3": "V_MID3[A1]",
"cycle": "CYCLE[A1]",
"t_early": "T_EARLY[A1]",
"t_late": "T_LATE[A1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_A1_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A1",
"para_sequence": 2,
"t_mid0": "T_MID0[A1]",
"t_mid1": "T_MID1[A1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_A1_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A1",
"para_sequence": 3,
"t_mid2": "T_MID2[A1]",
"t_mid3": "T_MID3[A1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_A1_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A1",
"para_sequence": 4,
"current": "CURRENT[A1]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"2B>current;"
]
},
"trig_timer_mode_set_A2": [
"trig_timer_mode_set_A2_para1",
"trig_timer_mode_set_A2_para2",
"trig_timer_mode_set_A2_para3",
"trig_timer_mode_set_A2_para4"
],
"trig_timer_mode_set_A2_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A2",
"para_sequence": 1,
"used": "USED[A2]",
"v_early": "V_EARLY[A2]",
"v_late": "V_LATE[A2]",
"v_mid0": "V_MID0[A2]",
"v_mid1": "V_MID1[A2]",
"v_mid2": "V_MID2[A2]",
"v_mid3": "V_MID3[A2]",
"cycle": "CYCLE[A2]",
"t_early": "T_EARLY[A2]",
"t_late": "T_LATE[A2]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_A2_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A2",
"para_sequence": 2,
"t_mid0": "T_MID0[A2]",
"t_mid1": "T_MID1[A2]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_A2_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A2",
"para_sequence": 3,
"t_mid2": "T_MID2[A2]",
"t_mid3": "T_MID3[A2]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_A2_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A2",
"para_sequence": 4,
"current": "CURRENT[A2]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"2B>current;"
]
},
"trig_timer_mode_set_A3": [
"trig_timer_mode_set_A3_para1",
"trig_timer_mode_set_A3_para2",
"trig_timer_mode_set_A3_para3",
"trig_timer_mode_set_A3_para4"
],
"trig_timer_mode_set_A3_para1": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A3",
"para_sequence": 1,
"used": "USED[A3]",
"v_early": "V_EARLY[A3]",
"v_late": "V_LATE[A3]",
"v_mid0": "V_MID0[A3]",
"v_mid1": "V_MID1[A3]",
"v_mid2": "V_MID2[A3]",
"v_mid3": "V_MID3[A3]",
"cycle": "CYCLE[A3]",
"t_early": "T_EARLY[A3]",
"t_late": "T_LATE[A3]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"5b>0;1b>v_late;1b>v_early;1b>used;",
"4b>0;1b>v_mid3;1b>v_mid2;1b>v_mid1;1b>v_mid0;",
"2B>cycle;4B>t_early;4B>t_late;"
]
},
"trig_timer_mode_set_A3_para2": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A3",
"para_sequence": 2,
"t_mid0": "T_MID0[A3]",
"t_mid1": "T_MID1[A3]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid0;4B>t_mid1;"
]
},
"trig_timer_mode_set_A3_para3": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A3",
"para_sequence": 3,
"t_mid2": "T_MID2[A3]",
"t_mid3": "T_MID3[A3]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"4B>t_mid2;4B>t_mid3;"
]
},
"trig_timer_mode_set_A3_para4": {
"type": "RIS",
"parameter": {
"mode": "MODE_ALL_OUTPUT",
"elite_ch": "ELITE_CH_A3",
"para_sequence": 4,
"current": "CURRENT[A3]"
},
"data": [
"1B>mode;",
"1B>elite_ch;",
"1B>para_sequence;",
"2B>current;"
]
}
}
}
+2 -8
View File
@@ -28,11 +28,5 @@ sudo su -c "psql -d postgres -c \"ALTER TABLE IF EXISTS project_report RENAME TO
# change table project_meta column cycle to type jsonb
sudo su -c "psql -d postgres -c \"ALTER TABLE project_metas ALTER COLUMN cycle type jsonb USING (cycle::jsonb);\"" postgres
# drop column calibration default
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ALTER COLUMN calibration DROP DEFAULT;\"" postgres
# drop column calibration default
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ALTER COLUMN calibration TYPE bytea USING calibration::bytea;\"" postgres
# add column project in recording_data_metas
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ADD COLUMN IF NOT EXISTS calibration_version Int4 DEFAULT -1;\"" postgres
# add column subject in project
sudo su -c "psql -d postgres -c \"ALTER TABLE projects ADD COLUMN IF NOT EXISTS subject JSONB;\"" postgres