Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99e9b84bde | |||
| 1f0ec7a350 | |||
| b7a78a229d | |||
| 10d563fca0 | |||
| 626ce1e2f5 | |||
| fd91546b8a | |||
| 8feab043d4 | |||
| 8d95fd3d5d | |||
| 25267411d8 | |||
| 200feead76 | |||
| f445550b4e | |||
| dfbbfe4e07 | |||
| 57e5c1a9e2 | |||
| ba192ccce8 |
@@ -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.
|
||||
|
||||
@@ -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, ...]:
|
||||
|
||||
@@ -163,12 +163,14 @@ def is_headstage_device(info: cc2650.GapEvt_DeviceInformation) -> Optional[Devic
|
||||
version_info[3],
|
||||
version_info[4],
|
||||
version_info[5])
|
||||
|
||||
return DeviceResponseInfo(local_name.decode(), serial_number, info.address, battery=battery_percentage)
|
||||
|
||||
elif company_code[:2] == b'HS':
|
||||
# legacy device
|
||||
|
||||
serial_number = DeviceSerialNumber(0, 0, 0, 0, 0, 0)
|
||||
|
||||
return DeviceResponseInfo(local_name.decode(), serial_number, info.address)
|
||||
|
||||
else:
|
||||
@@ -198,7 +200,7 @@ def is_headstage_device_central_version(device_mac: ADDRESS = EMPTY_ADDRESS,
|
||||
version_info[3],
|
||||
version_info[4],
|
||||
version_info[5])
|
||||
print('***********', version_info, device_mac)
|
||||
|
||||
return DeviceResponseInfo(local_name,
|
||||
serial_number,
|
||||
device_mac,
|
||||
@@ -481,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:
|
||||
@@ -2145,6 +2148,7 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
connected = False
|
||||
connect_response = None
|
||||
ins = bytearray()
|
||||
|
||||
ins.append(0x05)
|
||||
ins.append(0x08) #length
|
||||
ins.append(addr_type)
|
||||
@@ -2156,6 +2160,7 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
ins.append(address[5])
|
||||
ins.append(0xF1)
|
||||
self._interface.flush_input()
|
||||
|
||||
for retry in range(5):
|
||||
try:
|
||||
self.log_verbose('[CC2650]', 'connect att_write', '0x'+str.upper(ins.hex()))
|
||||
@@ -2178,14 +2183,21 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
if connect_response is None:
|
||||
return False
|
||||
|
||||
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
|
||||
@@ -2207,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))
|
||||
@@ -2221,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
|
||||
@@ -2253,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]
|
||||
@@ -2569,46 +2606,54 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
return ret
|
||||
|
||||
def connect(self, response: DeviceResponseInfo, direct_connect: bool = True) -> Device:
|
||||
def connect(self, response: DeviceResponseInfo, direct_connect: bool = False) -> Device:
|
||||
self.log_verbose('connect')
|
||||
|
||||
master = None
|
||||
print('self._foreach_empty_master()', self._foreach_empty_master())
|
||||
for master in self._foreach_empty_master():
|
||||
m = self._cc2650[master]
|
||||
d = self._device[master]
|
||||
print('master', master, d, m)
|
||||
if direct_connect is True and d is None:
|
||||
break
|
||||
|
||||
elif response in m.found() and d is None:
|
||||
break
|
||||
# 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
|
||||
|
||||
# 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:
|
||||
print('456')
|
||||
raise RuntimeError('rescan please')
|
||||
master = 4
|
||||
|
||||
#
|
||||
master = 4
|
||||
self.log_verbose('use', master)
|
||||
m = self._cc2650[master]
|
||||
d = self._device[master]
|
||||
print('4')
|
||||
|
||||
if d is not None:
|
||||
raise RuntimeError('cc2650 has connected a device')
|
||||
|
||||
with self:
|
||||
print('5')
|
||||
self._interface.flush()
|
||||
self._selector.select(master)
|
||||
|
||||
sleep(0.0001)
|
||||
d = m.connect(response, direct_connect)
|
||||
print('6')
|
||||
|
||||
if d is None:
|
||||
raise RuntimeError('connect failed, retry please')
|
||||
|
||||
@@ -683,12 +683,12 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
address = address_str(response.mac_address)
|
||||
self.log_info(DEVICE_CONNECTING, address)
|
||||
|
||||
# response = self.found_device(response)
|
||||
response = self.found_device(response)
|
||||
|
||||
# ''' device not found'''
|
||||
# if response is None:
|
||||
# self.log_warn(DEVICE_CONNECT_FAIL, address, DEVICE_NOT_FOUND)
|
||||
# return None
|
||||
''' device not found'''
|
||||
if response is None:
|
||||
self.log_warn(DEVICE_CONNECT_FAIL, address, DEVICE_NOT_FOUND)
|
||||
return None
|
||||
# raise RuntimeError(DEVICE_NOT_FOUND, address)
|
||||
|
||||
# get device library
|
||||
@@ -718,9 +718,7 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
serial_number=response.serial_number)
|
||||
else:
|
||||
try:
|
||||
print('here!!!!!!!!!!!!!!!!!!!!!!!', response)
|
||||
device = self._centralMaster.connect(response)
|
||||
print('connect', device)
|
||||
|
||||
device = CompletedDevice(self, library, device.device_id, device)
|
||||
except Exception as e:
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -532,7 +532,6 @@ class ComplexExpression(Expression[T]):
|
||||
@classmethod
|
||||
def parse(cls, json: JSON_OBJECT) -> Union['ComplexExpression', UndeterminedExpression]:
|
||||
expression = _get(json, 'expression', str, _truncate(json), nullable=True)
|
||||
print('expression parse', expression, json)
|
||||
|
||||
if expression is None:
|
||||
# un-determined expression
|
||||
@@ -880,13 +879,9 @@ class WhenExpression(ComplexExpression[T]):
|
||||
self._when: Dict[str, Expression[T]] = when
|
||||
|
||||
def value(self, context: Scope) -> Union[str, T]:
|
||||
print('value', context)
|
||||
value = super().value(context)
|
||||
|
||||
|
||||
key = str(value)
|
||||
print('value1', key,value)
|
||||
print('when', self._when)
|
||||
|
||||
if key in self._when:
|
||||
return self._when[key].value(context.child(VALUE=value))
|
||||
|
||||
@@ -404,9 +404,7 @@ class ListInstruction(Instruction, ImmutableListNode[Union[Instruction, Expressi
|
||||
ImmutableListNode.__init__(self, list(ins))
|
||||
|
||||
def eval_instruction(self, context: Scope) -> Iterable['SingleInstruction']:
|
||||
print('eval_instruction', context)
|
||||
for ins in self:
|
||||
print(ins)
|
||||
# foreach instructions
|
||||
|
||||
# ins type could be Union[str, Expression]
|
||||
@@ -796,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))
|
||||
|
||||
@@ -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]:
|
||||
@@ -1315,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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -329,30 +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)
|
||||
|
||||
version_info = [0, 5, 1, 0, 23, 5]
|
||||
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, 238, 89), 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()
|
||||
|
||||
@@ -582,6 +558,7 @@ class ControlServer(SocketServer, ControlServerAPI):
|
||||
response = content
|
||||
else:
|
||||
response = to_device_info(content)
|
||||
|
||||
try:
|
||||
ret = self.device_manager.connect(response)
|
||||
except DeviceInstructionError as e:
|
||||
@@ -891,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
|
||||
@@ -1201,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
|
||||
@@ -1421,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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"value": "VALUE"
|
||||
},
|
||||
"CYCLE": {
|
||||
"initial": [0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"initial": [1, 1, 1, 1, 1, 1, 1, 1],
|
||||
"domain": {
|
||||
"list": [
|
||||
0, 65535
|
||||
@@ -332,6 +332,7 @@
|
||||
"MODE": {
|
||||
"description": "working mode",
|
||||
"record_meta": true,
|
||||
"initial": 3,
|
||||
"value": [
|
||||
"Analog Current Control (ACC)",
|
||||
"Idle",
|
||||
|
||||
Reference in New Issue
Block a user