Compare commits

..

19 Commits

Author SHA1 Message Date
peterlu14 99e9b84bde - Add device mapping memory board No. 2024-08-09 17:44:16 +08:00
peterlu14 1f0ec7a350 - Add device attributes alert & alert_time
- Add reset_trigger function with parameter device
- Add api reset_trigger and device_alert to handle alerting problems
2024-04-12 17:37:23 +08:00
peterlu14 b7a78a229d -fix trigger time equal 0 error 2023-11-21 15:59:24 +08:00
peterlu14 10d563fca0 - fix len(c) is equal to zero 2023-11-16 14:19:42 +08:00
peterlu14 626ce1e2f5 -change test to device id 2023-11-15 15:17:27 +08:00
peterlu14 fd91546b8a -fix library 2023-07-18 18:36:39 +08:00
peterlu14 8feab043d4 -add trigger reset api
-change threshold to % & trigger to time
2023-07-18 11:13:30 +08:00
peterlu14 8d95fd3d5d -update threshold then send message 2023-07-14 09:54:58 +08:00
Roy 25267411d8 [update] fix connect & write function 2023-07-10 13:00:06 +08:00
peterlu14 200feead76 - update cycle default 1 2023-07-05 17:45:49 +08:00
Roy f445550b4e [update] update write gatt and fix read value of dev tool 2023-06-29 13:39:17 +08:00
Roy dfbbfe4e07 [update] set ram status register = 0x41 2023-06-26 17:34:45 +08:00
Roy 57e5c1a9e2 [update] fix eis mini calibration 2023-06-20 15:27:50 +08:00
Roy ba192ccce8 [update] print something debug info 2023-06-20 12:28:20 +08:00
peterlu14 aae1ab7a33 -update send instruction when trigger channel used 2023-06-14 12:02:35 +08:00
Roy 59148cff6d Feat(#6): new instruction of all output mode
https://www.notion.so/6-TRIG-s-All-output-mode-c382a9f88a444185873dbb62a7deee1a
2023-06-14 11:01:15 +08:00
Roy c9b10fc6aa [update] TRIG json 2023-06-13 13:23:58 +08:00
peterlu14 f82c3ab033 - add new mode 2023-06-13 09:51:43 +08:00
peterlu14 3884fad006 -update trigger 2023-06-13 09:33:31 +08:00
23 changed files with 1154 additions and 374 deletions
+6
View File
@@ -1595,6 +1595,12 @@ class ControlAPI(metaclass=Router):
def show_device_data(self, device) -> bool:
raise NotImplementedError()
def reset_trigger(self, device) -> bool:
raise NotImplementedError()
def device_alert(self, device) -> bool:
raise NotImplementedError()
# noinspection PyAbstractClass
class ControlClient(SocketClient, ControlAPI, metaclass=SocketClientMacro(ControlAPI)):
"""Connect to controller server through the socket.
+9
View File
@@ -139,6 +139,12 @@ class DataAPI(metaclass=abc.ABCMeta):
:param device: device ID
"""
pass
@abc.abstractmethod
def reset_trigger(self, device):
"""reset trigger
"""
pass
# noinspection PyAbstractClass
@@ -204,6 +210,9 @@ class DataClient(SocketClient, DataAPI, metaclass=SocketClientMacro(DataAPI)):
def show_data(self, device: int):
self.send_command('show_data', device)
def reset_trigger(self, device):
self.send_command('reset_trigger', device)
@staticmethod
def _to_device_id(*device: Union[int, Device]) -> Tuple[int, ...]:
+15 -30
View File
@@ -20,44 +20,29 @@ class Collection(Base):
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_collection(cls, collection_name, parent, duplicate=False):
def create_collection(cls, collection_name, parent):
with Session() as session:
name = cls.check_name_duplicate(collection_name, parent, 0, duplicate=duplicate)
if name == None:
return session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
else:
collection = Collection(
name = name,
parent = parent,
type= "folder",
)
session.add(collection)
session.commit()
session.refresh(collection)
return collection
name = cls.check_name_duplicate(collection_name, parent, 0)
collection = Collection(
name = name,
parent = parent,
type= "folder",
)
session.add(collection)
session.commit()
print('a', collection.id)
return collection
@classmethod
def check_name_duplicate(cls, collection_name, parent, n, _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()
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, _session)
return cls.check_name_duplicate(collection_name, parent, new_num)
@classmethod
def generate_name(cls, collection_name, n):
-24
View File
@@ -1,24 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from .base import Base, Session
class RecordingDataMeta(Base):
__tablename__ = "recording_data_metas"
id = Column(Integer, primary_key=True)
path = Column(String(255))
name = Column(String(255))
parent = Column(JSONB)
size = Column(String(255))
time_duration = (String(255))
raw_data = Column(JSONB)
project = Column(Integer)
deleted = Column(Boolean, default = False)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
# def __repr__(self):
# return f"User(id={self.id!r}, name={self.name!r}, fullname={self.task!r})"
-88
View File
@@ -1,88 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric, Text
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
# build a model class with a specific table name
def get_raw_model(channel):
tablename = str(channel) + '_recording_data_raws' # dynamic table name
class_name = 'RECORDING_DATA_RAWS' # dynamic class name
print('get_raw_model', tablename)
for mapper in Base.registry.mappers:
cls = mapper.class_
classname = cls.__name__
tblname = cls.__tablename__
print(cls, classname, tblname)
if (classname == class_name):
if tblname == tablename:
return cls
Model = type(class_name, (RECORDING_DATA_RAWS,), {
'__tablename__': tablename
})
return Model
class RECORDING_DATA_RAWS(Base):
__abstract__ = True
id = Column(Integer, primary_key=True)
name = Column(String(255))
parent = Column(Integer)
size = Column(String(255))
path = Column(JSONB)
uuid = Column(String(255))
serial_number = Column(String(255))
data_format = Column(String(255))
channel = Column(Integer)
start_time = Column(String(255))
end_time = Column(String(255))
data = Column(Text)
compressed = Column(Boolean)
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
# @classmethod
# def create_subject_data(cls, subject_id, project, meta, data):
# with Session() as session:
# subject = Subject(
# subject_id = subject_id,
# project = project,
# meta= meta,
# data = data
# )
# session.add(subject)
# session.commit()
# return subject
# @classmethod
# def check_name_duplicate(cls, collection_name, parent, n):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
# if result is None:
# return cls.generate_name(collection_name, n)
# else:
# new_num = n + 1
# # new_name = f"{collection_name}({new_num})"
# return cls.check_name_duplicate(collection_name, parent, new_num)
# @classmethod
# def generate_name(cls, collection_name, n):
# if n==0:
# return collection_name
# else:
# return f"{collection_name}({n})"
# @classmethod
# def find_data(cls, id):
# with Session() as session:
# result = session.query(RECORDING_DATA_RAWS).first()
# return result
-60
View File
@@ -1,60 +0,0 @@
from sqlalchemy import Table, Column, String, MetaData, ForeignKey, JSON
from sqlalchemy.sql import select, func
from sqlalchemy.types import Integer, BigInteger, String, Boolean, TIMESTAMP, Numeric
from sqlalchemy.dialects.postgresql import JSONB
from biopro.db.base import Session
from .base import Base
class SubjectData(Base):
__tablename__ = "subject_datas"
id = Column(Integer, primary_key=True)
subject_id = Column(Integer)
mode = Column(JSONB)
data = Column(JSONB)
user_auth = Column(JSONB)
meta = Column(String(255))
project = Column(String(255))
deleted = Column(Boolean)
created_at = Column(TIMESTAMP(timezone=True), server_default=func.now())
updated_at = Column(TIMESTAMP(timezone=True), onupdate=func.now())
@classmethod
def create_subject_data(cls, subject_id, project, meta, data):
with Session() as session:
subject = SubjectData(
subject_id = subject_id,
project = project,
meta= meta,
data = data
)
session.add(subject)
session.commit()
return subject
# @classmethod
# def check_name_duplicate(cls, collection_name, parent, n):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == cls.generate_name(collection_name, n), Collection.parent == parent).first()
# if result is None:
# return cls.generate_name(collection_name, n)
# else:
# new_num = n + 1
# # new_name = f"{collection_name}({new_num})"
# return cls.check_name_duplicate(collection_name, parent, new_num)
# @classmethod
# def generate_name(cls, collection_name, n):
# if n==0:
# return collection_name
# else:
# return f"{collection_name}({n})"
# @classmethod
# def find_collection(cls, collection_name, parent):
# with Session() as session:
# result = session.query(Collection).filter(Collection.name == collection_name, Collection.parent == parent).first()
# return result
+67 -22
View File
@@ -483,13 +483,14 @@ class CC2650Device(Device):
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
# mac1 = struct.unpack('<B', data[7:8])[0]
# mac2 = struct.unpack('<B', data[8:9])[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:
@@ -2185,12 +2186,18 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
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)
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)
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)
if connected == True:
# CC2650Device(device_id, master, scan_response) is a slave device
@@ -2212,7 +2219,7 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
ins.append(0xF1)
self._interface.flush_input()
for _ in range(5):
for retry in range(5):
try:
self.log_verbose('[CC2650]', 'disconnect att_write','0x'+str.upper(ins.hex()))
self._cc2650.send("bytes", bytes(ins))
@@ -2226,6 +2233,30 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
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
@@ -2258,6 +2289,7 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
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]
@@ -2579,21 +2611,34 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
master = None
for master in self._foreach_empty_master():
m = self._cc2650[master]
d = self._device[master]
# for master in self._foreach_empty_master():
# m = self._cc2650[master]
# d = self._device[master]
if direct_connect is True and d is None:
break
# if direct_connect is True and d is None:
# break
elif response in m.found() and d is None:
break
# elif response in m.found() and d is None:
# break
# else:
# if master is None:
# raise RuntimeError('cannot connect any more device')
# else:
# raise RuntimeError('rescan please')
mac_address = address_str(response.mac_address)
if mac_address == 'A4:DA:32:D4:E6:CD':
master = 4
elif mac_address == 'A4:DA:32:D4:E8:5F':
master = 5
elif mac_address == 'A4:DA:32:D4:E7:E5':
master = 6
elif mac_address == 'A4:DA:32:D4:EF:D8':
master = 7
else:
if master is None:
raise RuntimeError('cannot connect any more device')
else:
raise RuntimeError('rescan please')
master = 4
#
self.log_verbose('use', master)
+19 -1
View File
@@ -854,7 +854,8 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
__slots__ = ('_message', '_cycle_number', '_start_return_data', '_time_stamp',
'_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop', '_show_data')
'_mode_stop', '_show_data',
'_last_mem_wrong_information', '_last_mem_cnt', '_last_elite_notify_times')
def __init__(self):
super().__init__()
@@ -871,6 +872,10 @@ 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
@@ -935,6 +940,19 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
# 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]
+1
View File
@@ -794,6 +794,7 @@ 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))
+21 -5
View File
@@ -968,11 +968,10 @@ class CompletedDevice(Device):
"""
__slots__ = ('_master', '_device_id', '_device', '_library', '_context',
'_parameter', '_configuration', '_lock', '_feature_mask',
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project')
'_cache_battery', '_cache_battery_timestamp', '_coeff', '_status', '_occupied_by_project', '_alert', '_alert_time')
def __init__(self, master: MasterDevice, library: DeviceLibrary, device_id: int, device: Device):
"""
:param master: owner master device
:param library: device library
:param device_id: device id
@@ -1009,6 +1008,8 @@ class CompletedDevice(Device):
self._cache_battery: Optional[int] = None
self._cache_battery_timestamp: Optional[float] = None
self._coeff = b''
self._alert = False
self._alert_time = None
# device property for information
@@ -1092,6 +1093,22 @@ class CompletedDevice(Device):
def occupied_by_project(self, new_occupied_by_project):
self._occupied_by_project = new_occupied_by_project
@property
def alert(self) -> str:
return self._alert
@alert.setter
def alert(self, new_alert) -> str:
self._alert = new_alert
@property
def alert_time(self) -> str:
return self._alert_time
@alert_time.setter
def alert_time(self, new_alert_time) -> str:
self._alert_time = new_alert_time
# device parameter getter/setter
def parameters(self) -> List[str]:
@@ -1292,9 +1309,6 @@ class CompletedDevice(Device):
def central_version_get(self) -> Optional[list]:
return self._device.central_version_get()
def save_data_to_subject(self, project, meta, device, subject_id):
self._master._handler.save_data_to_subject(project, meta, device, subject_id)
# utility method
@@ -1318,6 +1332,8 @@ class CompletedDevice(Device):
'library_version': str(self._library.version),
'occupied_by_project': self._occupied_by_project,
'configuration': self.configuration.as_json(list_hide=True),
'alert': self.alert,
'alert_time': str(self.alert_time),
}
def __repr__(self):
+34 -19
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_0011 # 67
DEFAULT_REGISTER_VALUE = 0b0100_0001 # 0x41
MEM_SIZE = 0x1000
_SLEEP_TIME_ = 0.001
@@ -457,6 +457,16 @@ 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
@@ -493,28 +503,31 @@ class ExtMemManager:
ret[channel] = tuple(r)
print('ret=', ret)
return ret
@staticmethod
def is_no_device(result: Tuple[Optional[int], Optional[int]]) -> bool:
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]], channel: int) -> int:
r1, r2 = result
return (r1 is None or r2 is None) and (r1 is None or r1 == 0) and (r2 is None or r2 == 0)
r1_check = False
r2_check = False
@staticmethod
def is_memory_test_fail(result: Tuple[Optional[int], Optional[int]]) -> int:
r1, r2 = result
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('--------------------')
if r1 is None or r2 is None:
if r1_check and r2_check:
return 0
else:
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()
@@ -522,12 +535,14 @@ class ExtMemManager:
ret = []
for channel, result in enumerate(result):
if self.is_no_device(result):
continue
if self.is_memory_test_fail(result) != 0:
if self.is_memory_test_fail(result, channel) != 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
+1 -26
View File
@@ -49,9 +49,6 @@ 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')
@@ -72,10 +69,7 @@ class Project(threading.Thread):
collection = Collection.find_collection(default_name, default_parent)
parent = {"folder": [collection.id]}
# create project folder
folder_name_duplicate = False
if len(self._subject) > 0:
folder_name_duplicate = True
collection = Collection.create_collection(self.name, parent, folder_name_duplicate)
collection = Collection.create_collection(self.name, parent)
self.setup_collection(collection)
def setup_project(self, project):
@@ -107,22 +101,6 @@ class Project(threading.Thread):
@id.setter
def id(self, new_id):
self._id = new_id
@property
def project_meta_id(self) -> int:
return self._project_meta_id
@project_meta_id.setter
def project_meta_id(self, new_project_meta_id):
self._project_meta_id = new_project_meta_id
@property
def subject(self) -> object:
return self._subject
@subject.setter
def subject(self, new_subject):
self._subject = new_subject
@property
def uuid(self) -> str:
@@ -300,9 +278,6 @@ 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]}, False)
collection = Collection.create_collection(task.name, {"folder": [parent.id]})
task.parent = {"folder": [collection.id]}
else:
task.parent = {"folder": [parent.id]}
+33 -4
View File
@@ -22,6 +22,8 @@ import random
from copy import copy
import numpy as np
def json_stringify(o) -> str:
return _json_stringify(o, separators=(',', ':'))
@@ -1026,7 +1028,8 @@ class RecordingFileWriter:
'_mini_scale_list', '_time_real_time', '_data_rl', '_data_db',
'_raw_save', '_mini_save', '_data_time_ch', '_data_value_ch_for_rl',
'_data_time_ch_for_rl', '_device_id', '_send_data', '_data_mqtt_ch', '_id_db_save', '_raw_create_not_done',
'_mini_create_not_done')
'_mini_create_not_done', '_trigger_time', '_trigger_time_save', '_threshold', '_threshold_percent', '_first_average')
def __init__(self, meta: RecordingMetaFile, device_id, database = None):
self._meta = meta
@@ -1110,6 +1113,11 @@ class RecordingFileWriter:
self._raw_create_not_done = True
self._mini_create_not_done = True
self._trigger_time = 0
self._trigger_time_save = 0
self._threshold = 0
self._threshold_percent = 0
self._first_average = 0
@property
def meta_file(self) -> RecordingMetaFile:
@@ -1235,9 +1243,21 @@ class RecordingFileWriter:
ret.append(str(_max))
return ret
def get_data_iter(self, d, mqtt_thread):
def get_data_iter(self, d, mqtt_thread, mqtt_thread_1):
# print('****d size', d.data_size)
for t, c, v in d.entry_iter():
if c == 2:
# print(t,c,v, self._threshold, self._trigger_time)
# print(time(), time() - self._trigger_time)
if v > self._threshold:
self._trigger_time_save = time()
if (time() - self._trigger_time_save) > self._trigger_time and self._trigger_time_save != 0 and self._trigger_time != 0:
self._trigger_time_save = time()
content = {
'header': 'device_alert/0',
'device': self._device_id,
}
mqtt_thread_1.publish('device_alert', json_stringify(content), inter = True)
if c in self._data_db:
### send real-time
if len(self._data_rl[c]) > 0 and self._send_data[c]:
@@ -1330,7 +1350,7 @@ class RecordingFileWriter:
return
# @calculate_time(1)
def write(self, data: Union[bytes, RecordingData, List[bytes], List[RecordingData]], mqtt_thread) -> int:
def write(self, data: Union[bytes, RecordingData, List[bytes], List[RecordingData]], mqtt_thread, mqtt_thread_1) -> int:
# check size
ths = self.splitting_threshold_size
tht = self.splitting_threshold_time
@@ -1386,7 +1406,7 @@ class RecordingFileWriter:
'dec': 0,
}
self.get_data_iter(d, mqtt_thread)
self.get_data_iter(d, mqtt_thread, mqtt_thread_1)
if len(self._recording_file_dict) > 0:
for ch in self._data_db.keys():
@@ -1416,6 +1436,15 @@ class RecordingFileWriter:
if len(self._recording_file_dict) > 0:
for ch in self._data_db.keys():
if self._time_now - self._time[ch] > 5000000:
if ch == 2:
if self._first_average == 0:
a = np.array(self._data_db[ch], dtype=np.int64)
b = np.where(a % 2 == 1)[0]
c = a[b]
if len(c) != 0:
self._first_average = sum(c)/ len(c)
# print(c, self._first_average, self._threshold_percent)
self._threshold = self._first_average * (1 - (self._threshold_percent / 100))
if self._recording_file_dict[ch]._status:
_data = ' '.join(self._data_db[ch])
write_sz = self._recording_file_dict[ch].write(_data, self._channel_list)
+4
View File
@@ -717,6 +717,10 @@ class DataServer(SocketServer, DataAPI):
def show_data(self, device):
self._configurations[device].put_rec_queue('show_data')
def reset_trigger(self, device):
if self._configurations.get(device, None) != None:
self._configurations[device].put_rec_queue('reset_trigger')
class DataRuntime(metaclass=abc.ABCMeta):
__slots__ = ('_server', '_device', '_meta_file', '_data_format',
+29 -82
View File
@@ -35,11 +35,8 @@ from biopro.project.project_manager import ProjectManager
from biopro.db.base import Base, Session, engine
from biopro.db.project_report import ProjectReport
from biopro.db.project_meta import MetaProjectInfo
# from biopro.db.device import Device
from biopro.db.recording_data import get_raw_model
from biopro.db.subject_data import SubjectData
from biopro.db.meta import RecordingDataMeta
import random
from biopro.db.device import Device
_RUNTIME_COMPILE = False
@@ -332,18 +329,6 @@ class ControlServer(SocketServer, ControlServerAPI):
finally:
self.led_thread.set_state(LED.AVAILABLE)
# version_info = [0, 2, 1, 7, 23, 2]
# serial_number = DeviceSerialNumber(version_info[0],
# version_info[1],
# version_info[2],
# version_info[3],
# version_info[4],
# version_info[5])
# response = DeviceResponseInfo('Elite-EDC', serial_number, (164, 218, 50, 212, 231, 12), addr_type=0)
# print('setup done', response)
# ret = self.device_manager.connect(response)
# print('ret', ret)
def _setup_get_available_channel(self) -> Optional[List[int]]:
client = self.data_server.client()
@@ -573,15 +558,8 @@ class ControlServer(SocketServer, ControlServerAPI):
response = content
else:
response = to_device_info(content)
try:
# version_info = [0, 2, 1, 7, 23, 2]
# serial_number = DeviceSerialNumber(version_info[0],
# version_info[1],
# version_info[2],
# version_info[3],
# version_info[4],
# version_info[5])
# response = DeviceResponseInfo('Elite-EDC', serial_number, (164, 218, 50, 212, 231, 12))
ret = self.device_manager.connect(response)
except DeviceInstructionError as e:
'''when device reset fail error'''
@@ -890,7 +868,7 @@ class ControlServer(SocketServer, ControlServerAPI):
mac_address = address_str(connect_device.mac_address)
device = Device.get_device({"mac_address": mac_address})
try:
if connect_device.library.name.startswith('Elite_EIS_1.1'):
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
@@ -1129,7 +1107,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)
@@ -1143,12 +1121,10 @@ 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)
new_project = self.project_manager.get(device.occupied_by_project)
new_project.project_meta_id = _project_meta_id
project_meta_id = MetaProjectInfo.create_project_meta(project)
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:
@@ -1202,6 +1178,8 @@ class ControlServer(SocketServer, ControlServerAPI):
# unset file info, but keep file path cache
self.file_manager.unset(device.device_id)
device.status = 0
device.alert = False
device.alert_time = None
# server provide method implement : websocket broadcast functions
@@ -1378,57 +1356,6 @@ class ControlServer(SocketServer, ControlServerAPI):
} for pkg in PipPackage.list()]
return ret
def save_data_to_subject(self, project, meta, device, subject):
mode = device.get_parameter('MODE')
library = device.library_name
device = {
"library": library,
"mode": mode
}
# "pattern": {
# "id": number,
# "name": string,
# "parameter": object,
# },
# "data": {
# "id": list[int],
# "channel: list[int]
# }
with Session() as session:
meta_result = session.query(RecordingDataMeta).filter(RecordingDataMeta.project == meta).first()
self.mqtt_thread.publish('', json.dumps({
"pattern": {
"id": 4,
},
"data": {
"id": [meta_result.id],
"channel": ['Time', 6]
},
"others": {
"subject": subject,
"device": device,
"project": project,
"project_meta": meta,
}
}), analysis= True)
# result = session.query(recording_raws).order_by(recording_raws.id.desc()).first()
# value = result.data.split(' ')[1:-1:2]
# _value = list(map(int, value))
# sum_value = sum(_value)
# average_value = sum_value / len(_value)
# subject_data = SubjectData(
# subject_id= subject['id'],
# project = project,
# meta = meta,
# mode= device,
# data= average_value
# )
# # Execute the update query
# session.add(subject_data)
# session.commit()
def _hardware_send_test_hardware(self, section: Optional[str] = None) -> Dict[str, Any]:
if section is not None:
@@ -1473,6 +1400,26 @@ class ControlServer(SocketServer, ControlServerAPI):
if client is not None:
with client:
client.show_data(device)
@logging_info
def reset_trigger(self, device) -> bool:
device = self.device_manager.get_device(device)
client = self.data_server.client()
if client is not None:
with client:
device.alert = False
device.alert_time = None
client.reset_trigger(device.device_id)
self.broadcast_command('refresh')
@logging_info
def device_alert(self, device) -> bool:
device = self.device_manager.get_device(device)
device.alert = True
if device.alert_time == None:
device.alert_time = datetime.now()
self.broadcast_command('refresh')
class _RandomCrashThread(ServerThread):
def __init__(self):
super().__init__('Crash')
+1 -3
View File
@@ -170,11 +170,9 @@ class MqttThread(threading.Thread):
self.sleep(3)
self._mqtt_client_local.reconnect()
def publish(self, topic: str, payload: str, inter = False, analysis=False, qos = 2):
def publish(self, topic: str, payload: str, inter = False, qos = 2):
if inter:
_topic = self.__controller_ID + '_user'
elif analysis:
_topic = self.__controller_ID + '_data_analysis/get_analysis_data'
else:
_topic = self.__controller_ID + '/' + topic
if self._mqtt_client_local is not None:
+8 -2
View File
@@ -111,6 +111,10 @@ class RecordingProcess(Process):
self._decoder = self.data_format()
self._start_time = time()
self._writer = RecordingFileWriter(self._meta_file, self._device, self._database)
self._writer._threshold_percent = self._meta_file.configuration.get_parameter('THRESHOLD')
self._writer._trigger_time = self._meta_file.configuration.get_parameter('TRIGGER_TIME')
def ensure_data_format(self) -> DataDecodeFormat:
if isinstance(self._data_format, (str, bytes)):
self._data_format = DataDecodeFormat.parse(self._data_format)
@@ -187,6 +191,8 @@ class RecordingProcess(Process):
return False
elif q == 'show_data':
self._decoder._show_data = not self._decoder._show_data
elif q == 'reset_trigger':
self._writer._trigger_time_save = time()
else:
self.rec_update()
self.sync_data(q)
@@ -245,7 +251,8 @@ class RecordingProcess(Process):
if self._writer is not None and len(ret) > 0:
if len(self._writer.channel_list) == 0:
self._writer.channels_update(ret[0].channels())
self._writer.write(ret, self._mqtt_send_data_ch_level)
self._writer.write(ret, self._mqtt_send_data_ch_level, self._mqtt_thread)
# print('count', self._writer._count)
# print('write time: ', time() - ctime1)
# print(ret)
@@ -585,7 +592,6 @@ class RecordingProcess(Process):
self._is_close = False
if self._mqtt_thread is not None:
self._mqtt_thread.start()
self._writer = RecordingFileWriter(self._meta_file, self._device, self._database)
self.routine()
def routine(self) -> None:
@@ -43,6 +43,28 @@
},
"value": "VALUE"
},
"TRIGGER_TIME": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"THRESHOLD": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
1000
],
"value": {
"expression": "VALUE"
}
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -931,6 +931,28 @@
"ms"
]
},
"TRIGGER_TIME": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"THRESHOLD": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
1000
],
"value": {
"expression": "VALUE"
}
},
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
@@ -931,6 +931,28 @@
"ms"
]
},
"TRIGGER_TIME": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
"TIME_MAX"
],
"value": {
"expression": "VALUE"
}
},
"THRESHOLD": {
"description": "threshold ohm",
"record_meta": true,
"initial": 0,
"domain": [
1000
],
"value": {
"expression": "VALUE"
}
},
"TIME_DURATION": {
"description": "Run duration",
"record_meta": true,
@@ -10,9 +10,170 @@
},
"constant": {
"TIME_MAX": 100000,
"BLE_WRITE_MAX": 255
"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
},
"parameters": {
"USED": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"T_EARLY": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"V_EARLY": {
"initial": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"CYCLE": {
"initial": [1, 1, 1, 1, 1, 1, 1, 1],
"domain": {
"list": [
0, 65535
]
},
"value": "VALUE"
},
"T_MID0": {
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
"domain": {
"list": [
0, 86400000
]
},
"value": "VALUE"
},
"T_MID1": {
"initial": [0, 0, 0, 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": [false, false, false, false, false, false, false, false],
"domain": {
"list": [
0, 2
]
},
"value": "VALUE"
},
"V_MID1": {
"initial": [false, false, false, 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"
@@ -171,10 +332,12 @@
"MODE": {
"description": "working mode",
"record_meta": true,
"initial": 3,
"value": [
"Analog Current Control (ACC)",
"Idle",
"Dev Mode"
"Dev Mode",
"Trigger"
]
},
"CHANNEL": {
@@ -235,7 +398,8 @@
{
"expression": "MODE",
"when": {
"0": "curve_acc"
"0": "curve_acc",
"3": "trig_timer_mode"
}
},
"_sync(True)",
@@ -337,6 +501,677 @@
"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;"
]
}
}
}
+1 -4
View File
@@ -35,7 +35,4 @@ sudo su -c "psql -d postgres -c \"ALTER TABLE devices ALTER COLUMN calibration D
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
sudo su -c "psql -d postgres -c \"ALTER TABLE devices ADD COLUMN IF NOT EXISTS calibration_version Int4 DEFAULT -1;\"" postgres