Compare commits

..

32 Commits

Author SHA1 Message Date
Roy 8a870a860a [update] socket listen 3 -> 20 2022-10-05 10:57:30 +08:00
Roy f4c5cf0135 [update] socket timeout 1s -> 3s 2022-10-04 13:53:53 +08:00
Roy 1f01fd3b9b [update] count +1 when start 2022-10-04 13:53:30 +08:00
Roy d1fe388c27 [debug] fix multi device in one project stop problem 2022-10-04 13:42:03 +08:00
Roy 91d5e73c5e [debug] fix after task run equal error 2022-10-04 13:41:37 +08:00
Roy d1b6c2892f [debug] configurations key error 2022-10-04 13:18:38 +08:00
Roy 97188abff8 [update] uart write timeout 0.01 -> 1 2022-09-30 10:56:47 +08:00
Roy 9d8178d11a [update] add project cycle 2022-09-30 10:56:37 +08:00
Roy d182a04ed3 [update] add channel data 2022-09-14 15:36:01 +08:00
Roy 35a09ff9a0 [update] switch mode set default highz & time_duration in Elite_EDC 2022-09-06 18:51:32 +08:00
Roy e134b9780c [update] add new api set_project & add new condition until_button_trigger & add new action idle 2022-09-06 16:28:38 +08:00
peterlu14 df39f241b3 [update] add battery 2022-08-22 19:57:02 +08:00
peterlu14 0b72ac0c9d Merge branch 'dev/scheduler_cycle' into release/v1.6.6/merge_scheduler 2022-08-22 17:42:57 +08:00
JayC319 0afbe66229 [update] edc 1.5 library 2022-08-22 13:58:39 +08:00
108000207 9846cfd708 [update] set _time_interval as 0.1 to avoid delay 2022-08-19 15:44:51 +08:00
108000207 b4ad2a7fba [update] remove useless comments 2022-08-18 17:51:51 +08:00
108000207 675fdc2226 [update] cycle_next use uuid version 2022-08-18 17:39:59 +08:00
108000207 a847b1222d [debug] fix the bug of first task can't idle 2022-08-17 15:51:29 +08:00
108000207 bd0c36923a [update] scheduler cycle version 1 2022-08-17 11:50:22 +08:00
peterlu14 612785f51a [update] EIS show data 2022-08-16 19:40:27 +08:00
peterlu14 7dbf09e9a5 [update] EIS show data 2022-08-16 19:39:06 +08:00
peterlu14 ee64d43de1 [update] ca instruction b0 -> D3 2022-08-16 19:31:33 +08:00
peterlu14 60b91f0c1e [update] EIS add show data 2022-08-16 19:15:04 +08:00
Roy 8ac01bdf54 [update] update eis library 2022-08-16 19:10:18 +08:00
JayC319 0f90b16b6e [update] library product number 2022-08-16 17:35:06 +08:00
peterlu14 cd98a14e84 [debug] fix idle send instruction & remove deepcopy & close task by device 2022-08-16 14:25:37 +08:00
peterlu14 2e97ad23eb [debug] fix parameter empty 2022-08-16 12:11:35 +08:00
108000207 e0dd5a6972 [update] add schdeuler cycle attribute 2022-08-16 11:34:47 +08:00
Roy 76e0a150d1 Merge remote-tracking branch 'origin/dev/Cali_mode' into dev/cc_cp_separate 2022-08-15 18:11:20 +08:00
JayC319 ecd4b9325d [update] 2022-08-15 18:09:40 +08:00
peterlu14 978b1254f0 Merge branch 'dev/debug' into dev/cc_cp_separate 2022-08-11 13:53:13 +08:00
Roy 257958768f [update] new ca mode instruvtion 2022-08-05 18:34:33 +08:00
21 changed files with 748 additions and 131 deletions
+6
View File
@@ -1586,6 +1586,12 @@ class ControlAPI(metaclass=Router):
def stop_project(self, project) -> bool:
raise NotImplementedError()
def set_project(self, project, content) -> bool:
raise NotImplementedError()
def set_project_cycle(self, project, index, content) -> bool:
raise NotImplementedError()
def show_device_data(self, device) -> bool:
raise NotImplementedError()
+41 -31
View File
@@ -894,6 +894,10 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
finish_mode_falg = data[22]
battery = struct.unpack('<i', data[23:27])[0]
elite_notify_times = data[27]
notify_one = struct.unpack('<i', data[28:32])[0]
notify_two = struct.unpack('<i', data[32:36])[0]
notify_three = struct.unpack('<i', data[36:40])[0]
# self._show_data = True
mem_wrong_information = struct.unpack('<i', data[43:47])[0] # mem_wrong_information = green retry, green wrong, red retry, red wrong
ram_num = data[47]
@@ -919,8 +923,9 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
else:
if self._show_data:
print('|', time_stamp, '|', delta, '|', int(time_stamp * 1000 / 2),
'|', current, '|', voltage, '|', impedance,
'|', cycle_number, '|', finishMode, '@', str(self.device))
'|', current, '|', voltage, '|', impedance, '|', cycle_number,
'|', notify_one, '|', notify_two, '|', notify_three,
'|', finishMode, '@', str(self.device))
# print('|', '{:10}'.format(time_stamp),
# '|', '{:4}'.format(delta),
@@ -949,6 +954,9 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
ret.append_data(1, voltage)
ret.append_data(2, impedance)
ret.append_data(3, cycle_number)
ret.append_data(4, notify_one)
ret.append_data(5, notify_two)
ret.append_data(6, notify_three)
# ret.append_data(4, battery)
# ret.append_data(5, elite_notify_times)
# ret.append_data(6, mem_cnt)
@@ -1338,7 +1346,7 @@ class EISZeroOneDataDecoder(RecDataDecoder):
'_total_time_stamp', '_mode', '_cycle_start_time',
'_mode_stop', '_last_time_stamp', '_last_delta', '_cali_coeff',
'cali_coeff', '_ac_amp', '_mode', '_freq_start', '_freq_stop',
'_freq_direction', '_last_phase', '_first_phase_flag')
'_freq_direction', '_last_phase', '_first_phase_flag', '_show_data')
def __init__(self, cali_coeff: bytes = None):
super().__init__()
@@ -1362,6 +1370,8 @@ class EISZeroOneDataDecoder(RecDataDecoder):
self._cali_coeff: Optional[bytes] = None
self.cali_coeff: Optional[List[Tuple[int, int]]] = None
self._show_data = False
if cali_coeff is not None:
self._cali_coeff = cali_coeff
self.cali_coeff = self._decode_cali_coeff(cali_coeff)
@@ -1546,34 +1556,34 @@ class EISZeroOneDataDecoder(RecDataDecoder):
imag_after_cal = impedance * math.sin(round(phase) * math.pi / 180)
real_after_cal = impedance * math.cos(round(phase) * math.pi / 180)
if (self._mode == 0):
# print('|', '{:10}'.format(time_stamp),
# '|', '{:5}'.format(delta),
# '|', '{:6}'.format(ch1),
# '|', '{:6}'.format(ch2),
# '|', '{:8}'.format(ch3 / 100),
# '|', '{:6}'.format(round(voltage_mag)),
# '|', '{:5}'.format(int(imag_after_cal)),
# '|', '{:5}'.format(int(real_after_cal)),
# '|', '{:5}'.format(round(impedance)),
# '|', '{:5}'.format(round(phase, 1)),
# '|', '{:5}'.format(round(current, 3)),
# '|', '{:1}'.format(gain),
# '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|')
pass
else:
# print('|', '{:10}'.format(time_stamp),
# '|', '{:5}'.format(delta),
# '|', '{:5}'.format(ch1),
# '|', '{:5}'.format(ch2),
# '|', '{:5}'.format(ch3),
# '|', '{:5}'.format(cycle_number),
# '|', '{:1}'.format(gain),
# '|', '{:1}'.format(finishMode),
# '@', str(self.device), '|')
pass
if self._show_data:
if (self._mode == 0):
print('|', '{:10}'.format(time_stamp),
'|', '{:5}'.format(delta),
'|', '{:6}'.format(ch1),
'|', '{:6}'.format(ch2),
'|', '{:8}'.format(ch3 / 100),
'|', '{:6}'.format(round(voltage_mag)),
'|', '{:5}'.format(int(imag_after_cal)),
'|', '{:5}'.format(int(real_after_cal)),
'|', '{:5}'.format(round(impedance)),
'|', '{:5}'.format(round(phase, 1)),
'|', '{:5}'.format(round(current, 3)),
'|', '{:1}'.format(gain),
'|', '{:1}'.format(finishMode),
'@', str(self.device), '|')
pass
else:
print('|', '{:10}'.format(time_stamp),
'|', '{:5}'.format(delta),
'|', '{:5}'.format(ch1),
'|', '{:5}'.format(ch2),
'|', '{:5}'.format(ch3),
'|', '{:5}'.format(cycle_number),
'|', '{:1}'.format(gain),
'|', '{:1}'.format(finishMode),
'@', str(self.device), '|')
pass
if finishMode == True:
print("finishMode full data:", list(data), datetime.now())
+7
View File
@@ -1105,6 +1105,8 @@ class CompletedDevice(Device):
return self._configuration.get_parameter(name, False)
def set_multi_parameters(self, parameter):
if len(parameter) == 0:
return
for (name, value) in parameter[0].items():
if name != 'target':
self.set_parameter(name, value)
@@ -1128,6 +1130,11 @@ class CompletedDevice(Device):
self._parameter.set_parameter(name, value)
# raise RuntimeError('illegal parameter value : ' + value) from e
else:
if name == 'MODE':
if self.library_name.startswith('Elite_EDC'):
self.set_parameter('CTRL_HIGH_Z_15', self.get_parameter('HIGHZ_TABLE')[value])
self.set_parameter('TIME_DURATION', 0)
self._parameter.set_parameter(name, value)
on_change = info.on_change
+1 -1
View File
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
self._serial = serial.Serial(self._port,
baudrate=self._baudrate,
timeout=0,
writeTimeout=0.01)
writeTimeout=1)
# deprecate function name which change at version 3.0
self._serial.flushInput()
self._serial.flushOutput()
+8
View File
@@ -24,3 +24,11 @@ class Action():
@property
def condition(self):
return self._condition
def as_json(self):
return {
'id': self._id,
'type': self._type,
'target': self._target,
'condition': self._condition
}
+61 -12
View File
@@ -45,8 +45,8 @@ class Condition():
# print(operator, x, y)
cases = {
"equal": lambda a, b: a == b,
"bigger": lambda a, b: a > b,
"smaller": lambda a, b: a < b,
"bigger": lambda a, b: a >= b,
"smaller": lambda a, b: a <= b,
}
return cases[operator](x, y)
@@ -56,7 +56,8 @@ class Condition():
return getattr(self, self.type)(**kwargs)
def absolute_time(self, **kwargs):
now = int(time())
# now = int(time())
now = round(time(), 1)
time_condition = round(self.datetime_to_timestamp(self.str_to_datetime(self._value)))
return self.compareWith(self.comparsion, now, time_condition)
@@ -65,32 +66,80 @@ class Condition():
project_start_time = kwargs['project_start_time']
delay_time = kwargs['delay_time']
time_diff = int(time() - project_start_time - delay_time)
return self.compareWith(self.comparsion, time_diff, int(self._value))
# time_diff = int(time() - project_start_time - delay_time)
time_diff = round(time() - project_start_time - delay_time, 1)
return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
def after_task_run(self, **kwargs):
# print('relative_time_from_task', kwargs,kwargs['task_start_time'],kwargs['delay_time'])
# print('relative_time_from_task', kwargs['task_start_time'],kwargs['delay_time'])
if len(kwargs['task_start_time']) == 0:
return False
task = kwargs['self_task']
running_task = kwargs['running_task']
task_start_time = kwargs['task_start_time'][-1]
delay_time = kwargs['delay_time']
time_diff = int(time() - task_start_time - delay_time)
# print('time_diff', time_diff)
return self.compareWith(self.comparsion, time_diff, int(self._value))
time_diff = round(time() - task_start_time - delay_time, 1)
# print('real_diff', time() - task_start_time - delay_time)
# print(task.name, task.uuid, time_diff, round(int(self._value), 1), running_task.name, running_task.uuid)
# if round(int(self._value), 1) == 0 and time_diff == 0.1:
# return True
if task.uuid != running_task.uuid:
return False
return self.compareWith('bigger', time_diff, round(int(self._value), 1))
# return self.compareWith(self.comparsion, time_diff, round(int(self._value), 1))
def device(self, **kwargs):
print('device')
def previous_task_done(self, **kwargs):
""" def previous_task_done(self, **kwargs):
running_task = kwargs['running_task']
if running_task.status == 2 and self._active == False:
self._active = True
return True
return False """
def previous_task_done(self, **kwargs):
running_task = kwargs['running_task']
self_task = kwargs['self_task']
# if running_task != None and self_task != None:
# print('\nprevious_task_done: ', running_task.status, ' ', self._active)
if running_task != self_task:
if running_task == None:
return True
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False
def until_button_trigger(self, **kwargs):
running_task = kwargs['running_task']
if running_task != None:
if running_task.button_trigger == True:
running_task.button_trigger = False
return True
return False
""" def cycle(self, **kwargs):
running_task = kwargs['running_task']
self_task = kwargs['self_task']
if running_task != self_task:
if running_task.status == 2 and self._active == False:
# self._active = True
return True
return False """
def str_to_datetime(self, time_str):
return datetime.strptime(time_str,'%Y-%m-%dT%H:%M')
def datetime_to_timestamp(self, date):
return datetime.timestamp(date)
return datetime.timestamp(date)
def as_json(self):
return {
'id': self._id,
'type': self._type,
'comparsion': self._comparsion,
'value': self._value,
'active': self._active
}
+6 -1
View File
@@ -22,6 +22,7 @@ class Instruction():
self._start_instruction = list(map(lambda ins: self._instruction_set[ins] ,['set_file_name', 'set_parent', 'set_parameter', 'call_instruction']))
self._stop_instruction = list(map(lambda ins: self._instruction_set[ins] ,['call_instruction']))
self._idle_instruction = []
@property
def start(self) -> list:
@@ -29,4 +30,8 @@ class Instruction():
@property
def stop(self) -> list:
return self._stop_instruction
return self._stop_instruction
@property
def idle(self) -> list:
return self.idle_instruction
+118 -24
View File
@@ -19,12 +19,12 @@ key_list = {
}
class Project(threading.Thread):
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, name="project"):
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, log_verbose = None, name="project"):
super(Project, self).__init__(name = name)
self._project = project
self._device_manager = device_manager
self._mqtt_thread = mqttThread
self._time_interval = 1
self._time_interval = 0.1
self._start_time = None
self._end_time = None
@@ -41,6 +41,12 @@ class Project(threading.Thread):
self._task_manager = None
self._cycle = []
self._count = 1 #流水號
self.log_verbose = log_verbose
self.setup_project(project)
self.setup_device(self._device)
@@ -50,7 +56,7 @@ class Project(threading.Thread):
key = key_list[key]
if key == 'task':
self._task_manager = TaskManager(project['task'])
self._task_manager = TaskManager(project['task'], project['cycle'])
elif key == 'uuid':
pass
else:
@@ -84,6 +90,14 @@ class Project(threading.Thread):
@name.setter
def name(self, new_name):
self._name = new_name
@property
def cycle(self) -> list:
return self._cycle
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
@property
def desc(self) -> str:
@@ -117,9 +131,14 @@ class Project(threading.Thread):
def mqtt_thread(self):
return self._mqtt_thread
@property
def running_task(self):
return self._task_manager.running_task
def run(self):
self._status = 1
self._start_time = time()
self.log_verbose('Project ' + self.name + ' start')
self.mqtt_thread.broadcast_command('project:' + self._name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
while not self._stop_flag :
@@ -130,41 +149,92 @@ class Project(threading.Thread):
for task in check_list:
if task != None:
now = time()
# print('round task', task.name)
# print('running task', self._task_manager.running_task.name, self._task_manager.running_task.status)
# if self._task_manager.prev_task != None:
# print('previous_task', self._task_manager.prev_task.name, self._task_manager.prev_task.status)
match_condition_list = task.check_condition(
project_start_time = self._start_time,
delay_time = delay_time,
running_task= self._task_manager.running_task,
previous_task = self._task_manager.prev_task
previous_task = self._task_manager.prev_task,
self_task = task
)
# print('match_condition_list', match_condition_list)
for condition in match_condition_list:
match_action_list = task.get_match_action(condition.id)
for action in match_action_list:
# print('match_action', action.type, action.target)
if action.type == 'start' and task.status != 1:
self._task_manager.set_running_task(task)
if action.type == 'cycle' and condition.type == 'previous_task_done':
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._task_manager.set_running_task(task)
if action.type == 'cycle' and condition.type == 'until_button_trigger':
self._task_manager.running_task.stop()
device = self._complete_device[action.target]
task_info = task.get_task_info(action)
instruction_set = getattr(self._instruction_set, action.type, None)
# print('instruction_set',instruction_set)
if instruction_set != None:
for instruction in instruction_set:
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
threading.Thread(target=getattr(device, instruction['method'])(*args))
if self._task_manager.running_task != None:
if self._task_manager.running_task.uuid == task.uuid and action.type == 'cycle' and condition.type == 'after_task_run':
self._task_manager.running_task.stop()
if action.type == 'start':
if task.status != 1:
self._task_manager.set_running_task(task)
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# elif action.type == 'stop':
# self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
# self._count += 1
# if self.check_running_task_not_run() == True:
# self._task_manager.running_task.stop()
elif action.type == 'idle':
self._task_manager.running_task.stop()
instruction_set = None
if action.target is not None:
device = self._complete_device[action.target]
if ((action.type == 'start' and device.status == 0) or (action.type == 'stop' and device.status == 1)):
self.log_verbose('Project' + self.name + 'Task ' + task.name + ' match_condition ' + condition.type + ' trigger_action ' + action.type + ' ' + str(action.target))
task_info = task.get_task_info(action)
instruction_set = getattr(self._instruction_set, action.type, None)
# 檔名修正
# device
task_info['file_name'] += '#' + device.mac_address_in_str[12:].upper()
# 流水號
task_info['file_name'] += '#' + str(self._count)
# 添加cycle資訊
if len(self.cycle) > 0:
index = self._task_manager.get_index_by_task(task)
# get list of cycle determine by index of task
filtered = list(filter(lambda info: self._task_manager.get_index_by_uuid(info['range'][0]) < index and self._task_manager.get_index_by_uuid(info['range'][1]) > index, self.cycle))
if len(filtered) == 0:
pass
elif len(filtered) == 1:
if filtered[0]['useID'] == True:
task_info['file_name'] += '#' + str(filtered[0]['id'])
else:
task_info['file_name'] += '#' + str(filtered[0]['name']) + '-' + str(filtered[0]['count'])
else:
# if multi cycle, then sort by range from task index to cycle start index, then loop concat filename
filtered.sort(key=lambda info: abs(self._task_manager.get_index_by_uuid(info['range'][0]) - index))
for cycle_info in filtered:
if cycle_info['useID'] == True:
task_info['file_name'] += '#' + str(cycle_info['id'])
else:
task_info['file_name'] += '#' + str(cycle_info['name']) + '-' + str(cycle_info['count'])
self.log_verbose('file name ' + task_info['file_name'])
if instruction_set != None and len(task.parameter_set) > 0:
if action.type == 'start':
self._count += 1
for instruction in instruction_set:
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
target=getattr(device, instruction['method'])(*args)
delay_time += (time() - now)
# check task not running then stop
if self.check_running_task_not_run() == True:
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
if self._task_manager.running_task.type == '':
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
self._task_manager.running_task.stop()
# check project done then close project
@@ -200,11 +270,34 @@ class Project(threading.Thread):
return False
return True
def set_content(self, content):
self.running_task.button_trigger = True
def set_cycle(self, index, content):
# change cycle name
for key in content:
self.cycle[index][key] = content[key]
# change task name
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][0]).name = content['name']
# self._task_manager.get_task_by_uuid(self.cycle[index]['range'][1]).name = content['name']
def check_running_task_not_run(self):
# if no running task
if self._task_manager.running_task == None:
return False
# if running is cycle then no need to stop by device
if self._task_manager.running_task.type == 'cycle':
return False
for key in self._task_manager.running_task.action:
# print('action key', key, self._task_manager.running_task, self._task_manager.running_task.action[key])
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'stop':
return False
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'idle':
return False
for device in self._task_manager.running_task.device:
if self._complete_device[device].status == 1:
return False
@@ -222,6 +315,7 @@ class Project(threading.Thread):
'status': self._status,
'device': self._device,
'task': self.task_list,
'running_task': running_task
'running_task': running_task,
'cycle': self._cycle
}
return data
+11 -2
View File
@@ -9,13 +9,14 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':'))
class ProjectManager():
def __init__(self, device_manager: DeviceManager, mqtt_thread=None) :
def __init__(self, device_manager: DeviceManager, mqtt_thread=None, log_verbose = None) :
self._project_list = []
self._mqtt_thread = mqtt_thread
self._device_manager = device_manager
self.log_verbose = log_verbose
def create(self, project):
new_project = Project(project, self._device_manager, self._mqtt_thread)
new_project = Project(project, self._device_manager, self._mqtt_thread, self.log_verbose)
self._project_list.append(new_project)
return new_project
@@ -37,3 +38,11 @@ class ProjectManager():
def stop_project(self, project):
_project = self.get(project)
_project.stop()
def set_project(self, project_uuid, content):
_project = self.get(project_uuid)
_project.set_content(content)
def set_project_cycle(self, project_uuid, index, content):
_project = self.get(project_uuid)
_project.set_cycle(index, content)
+62 -2
View File
@@ -12,29 +12,39 @@ key_list = {
class Task:
def __init__(self, task):
self._id = None
self._uuid = None
self._type = None
self._name = None
self._parent = None
self._cycle = None
self._cycle_count = 0
self._cycle_next = None
self._cycle_next_uuid = None
self._device = None
self._event = None
self._trigger = None
self._parameter_set = None
self._condition = None
self._action = None
# -1: initial 0: start(idle), 1: running, 2: close(idle)
# -1: init 0: start(idle), 1: run, 2: close(idle)
self._status = 0
self._next = None
# action & condition info
self._condition_list: List[Condition] = []
self._action_list: List[Action] = []
self._instruction_list = []
self._record_list = []
# time info
self._start_time = []
self._idle_time = []
self._end_time = []
self._period = None
# trigger info
self._button_trigger = False
self.load_task(task)
def load_task(self, task) -> None:
@@ -74,6 +84,14 @@ class Task:
@uuid.setter
def uuid(self, new_uuid):
self._uuid = new_uuid
@property
def type(self):
return self._type
@type.setter
def type(self, new_type):
self._type = new_type
@property
def name(self):
@@ -100,6 +118,31 @@ class Task:
@cycle.setter
def cycle(self, new_cycle):
self._cycle = new_cycle
# TODO: not sure needed?
@property
def cycle_count(self) -> int:
return self._cycle_count
@cycle_count.setter
def cycle_count(self, new_cycle_count):
self._cycle_count = new_cycle_count
@property
def cycle_next(self) -> str:
return self._cycle_next
@cycle_next.setter
def cycle_next(self, new_cycle_next):
self._cycle_next = new_cycle_next
@property
def cycle_next_uuid(self) -> str:
return self._cycle_next_uuid
@cycle_next_uuid.setter
def cycle_next_uuid(self, new_cycle_next_uuid):
self._cycle_next_uuid = new_cycle_next_uuid
@property
def device(self) -> dict:
@@ -177,6 +220,14 @@ class Task:
def end_time(self) -> List:
return self._end_time
@property
def button_trigger(self) -> List:
return self._button_trigger
@button_trigger.setter
def button_trigger(self, button_trigger):
self._button_trigger = button_trigger
def new_start_time(self):
self._start_time.append(time())
@@ -207,6 +258,10 @@ class Task:
def stop(self):
self.status = 2
def reset(self):
self.status = -1
# self.status = 0
def get_match_action_list(self, match_condition_list):
return map(lambda condition: [x for x in self._action_list if condition.id in x.get_condition_list()], match_condition_list)
@@ -230,7 +285,7 @@ class Task:
return {
'device': action.target,
'parameter': self.get_parameter_set_by_device(action.target),
'file_name': self._name + '-' + str(action.target),
'file_name': self._name,
'parent': self.parent,
'instruction': _type
}
@@ -240,7 +295,12 @@ class Task:
'id': self.id,
'name': self.name,
'parent': self.parent,
'type': self.type,
'uuid': self.uuid,
'cycle': self.cycle,
'cycle_count': self.cycle_count,
'cycle_next': self.cycle_next,
'cycle_next_uuid': self.cycle_next_uuid,
'device': self.device,
'event': self.event,
'trigger': self.trigger,
+66 -2
View File
@@ -12,11 +12,12 @@ def json_stringify(o: Any) -> str:
return _json_stringify(o, separators=(',', ':'))
class TaskManager():
def __init__(self, task_list):
def __init__(self, task_list, cycle_list):
self._task_list = []
self._next_task = []
self._prev_task = None
self._running_task = None
self._cycle_list = cycle_list
self.load_task_list(task_list)
@@ -44,6 +45,23 @@ class TaskManager():
def next_task(self):
return self._next_task
def get_task_by_index(self, index):
return self._task_list[index]
def get_task_by_uuid(self, uuid):
return next((x for x in self.task_list if x.uuid == uuid), None)
def get_index_by_task(self, task):
return next((i for i, x in enumerate(self.task_list) if x.uuid == task.uuid), None)
def get_index_by_uuid(self, uuid):
return next((i for i, x in enumerate(self.task_list) if x.uuid == uuid), None)
def check_task_is_cycle_end(self, task):
for index, cycle in enumerate(self._cycle_list):
if cycle['range'][1] == task.uuid:
return index
@property
def check_list(self):
return [self._running_task, *self._next_task]
@@ -57,7 +75,8 @@ class TaskManager():
task = Task(task)
self._task_list.append(task)
def set_running_task(self, task):
# original version
""" def set_running_task(self, task):
try:
# if there is task running & same task active ,then reject
if self._running_task != None and self._running_task.uuid == task.uuid:
@@ -80,6 +99,51 @@ class TaskManager():
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
self._next_task.append(_task)
except RuntimeError as e:
print(e) """
def set_running_task(self, task):
try:
# if there is task running & same task active ,then reject
if self._running_task != None and self._running_task.uuid == task.uuid:
return False
# save task
self._prev_task = self._running_task
# clear next task list
self._next_task.clear()
# set task to running_task
self._running_task = task
self._running_task.run()
# if previous task is still running, then need to close
if self._prev_task != None:
if self._prev_task.status == 1:
self._prev_task.stop()
# if reach cycle end, count < max, then go to cycle start
cycle_index = self.check_task_is_cycle_end(task)
if cycle_index is None:
# print('next', self._running_task.name, self._running_task.next)
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
# print('self._next_task', self._next_task)
else:
# print('cycle', self._cycle_list[cycle_index])
cycle = self._cycle_list[cycle_index]
if int(cycle['count']) < int(cycle['max']):
self._next_task.append(self.get_task_by_uuid(cycle['range'][0]))
cycle['count'] += 1
else:
for task_uuid in self._running_task.next:
_task = next((task for task in self._task_list if task.uuid == task_uuid), None)
if _task != None:
_task.reset()
self._next_task.append(_task)
cycle['count'] = 1
except RuntimeError as e:
print(e)
+10 -8
View File
@@ -65,7 +65,7 @@ class DataServer(SocketServer, DataAPI):
"""
global _FLAG_DATA_LOST_STATS_
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=3)
super().__init__(DataAPI, 'DataServer', self.ADDR, socket_listen=20)
data_options = DataServerOptions.get_options(*options)
@@ -664,13 +664,15 @@ class DataServer(SocketServer, DataAPI):
data = None
if data is not None:
if self._configurations[device].queue_flag:
self._configurations[device].queue_flag = False
print("q size= ", self._configurations[device]._queue_rec.qsize())
self._configurations[device].put_rec_queue(data)
# self._no_data_total_duration = 0
ret = True
if self._configurations.get(device, None) != None:
if self._configurations[device].queue_flag:
self._configurations[device].queue_flag = False
print("q size= ", self._configurations[device]._queue_rec.qsize())
if self._configurations.get(device, None) != None:
self._configurations[device].put_rec_queue(data)
# self._no_data_total_duration = 0
ret = True
# else:
# time_diff = time() - self._recv_memory_cost_time
# self._no_data_total_duration += time_diff
+26 -7
View File
@@ -105,7 +105,7 @@ class ControlServer(SocketServer, ControlServerAPI):
# device detect
self._detect_device_thread = RoutineConnectDeviceThread(self._device_manager, self.mqtt_thread, self.led_thread, 3)
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread)
self._project_manager = ProjectManager(self.device_manager, self.mqtt_thread, self.log_verbose)
if not c.flag_disable_led_control:
self.led_thread.set_state(LED.COLOR_RED)
@@ -819,12 +819,18 @@ class ControlServer(SocketServer, ControlServerAPI):
return True
@logging_info
def device_battery(self) -> List[int]:
device_list = self.device_manager.list_device()
if len(device_list) > 0:
battery_list = list(map(lambda x: self.device_manager.get_device(x).battery, device_list))
return battery_list
def device_battery(self, device:int) -> List[int]:
battery = {}
if device == 'all':
device_list = self.device_manager.list_device()
if len(device_list) > 0:
battery = list(map(lambda x: {"device": x.memory_board, "battery":self.device_manager.get_device(x).battery}, device_list))
else:
battery = {
"device": device,
"battery": self.device_manager.get_device(device).battery
}
return battery
@logging_info
def device_parent(self, device: int, content: Optional[str] = None) -> List[int]:
@@ -1015,6 +1021,7 @@ class ControlServer(SocketServer, ControlServerAPI):
@logging_info
def run_project(self, project) -> bool:
if project is not None:
# print(project)
project = self._project_manager.create(project)
self._project_manager.run_project(project)
return project.as_json()
@@ -1024,6 +1031,18 @@ class ControlServer(SocketServer, ControlServerAPI):
if project is not None:
self._project_manager.stop_project(project)
return True
@logging_info
def set_project(self, project, content) -> bool:
if project is not None:
self._project_manager.set_project(project, content)
return True
@logging_info
def set_project_cycle(self, project, index, content) -> bool:
if project is not None:
self._project_manager.set_project_cycle(project, index, content)
return True
@logging_info
def get_running_project(self) -> bool:
+7 -5
View File
@@ -93,13 +93,15 @@ class SocketClient(metaclass=abc.ABCMeta):
if self._socket is None:
try:
self._socket = Socket(AF_UNIX, SOCK_STREAM)
self._socket.settimeout(1)
self._socket.settimeout(3)
self._socket.connect(self._socket_file)
except FileNotFoundError as e:
raise RuntimeError('server not available') from e
except Exception as e:
print('open_socket error:', e)
# except FileNotFoundError as e:
# raise RuntimeError('server not available') from e
except ConnectionRefusedError as e:
raise RuntimeError('server crash') from e
# except ConnectionRefusedError as e:
# raise RuntimeError('server crash') from e
def close_socket(self):
if self._socket is not None:
@@ -1203,7 +1203,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X07;",
"X0C;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -15,6 +15,33 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -671,6 +698,17 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -836,6 +874,18 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -851,7 +901,8 @@
"initial": 0,
"value": [
"Iin",
"Vin"
"Vin",
"Vout"
]
},
"BLE_WRITE": {
@@ -912,11 +963,13 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin"
"1": "cali_Vin",
"2": "cali_Vout"
}
},
"_sync(True)",
@@ -1007,12 +1060,6 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1025,6 +1072,12 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1052,6 +1105,15 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
@@ -1203,7 +1265,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X07;",
"X0C;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -15,6 +15,33 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -671,6 +698,17 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -836,6 +874,18 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -851,7 +901,8 @@
"initial": 0,
"value": [
"Iin",
"Vin"
"Vin",
"Vout"
]
},
"BLE_WRITE": {
@@ -912,11 +963,13 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin"
"1": "cali_Vin",
"2": "cali_Vout"
}
},
"_sync(True)",
@@ -1007,12 +1060,6 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1025,6 +1072,12 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1052,6 +1105,15 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
@@ -1203,7 +1265,7 @@
"pe": "SAMPLE_RATE"
},
"data": [
"X07;",
"X0C;",
"B>va;4B>vb;2B>vc;2B>vd;",
"4b>pa;4b>pb;",
"4b>pc;4b>pd;",
@@ -15,6 +15,33 @@
"BLE_WRITE_MAX": 255
},
"parameters": {
"HIGHZ_TABLE": {
"initial": [
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
1,
1,
1,
0,
1,
1,
1
],
"domain": {
"list": [
100
]
},
"value": "VALUE"
},
"DPV_e_init": {
"description": "DPV initial voltage ",
"record_meta": true,
@@ -671,6 +698,17 @@
},
"on_change": "set_para_DAC_VOLT"
},
"DAC_VOLT_SCROLL": {
"description": "DAC scroll output Voltage",
"record_meta": true,
"initial": 25000,
"domain": [
65536
],
"value": {
"expression": "VALUE"
}
},
"ADC_VALUE_I": {
"description": "ADC value current value",
"domain": "int"
@@ -836,6 +874,18 @@
],
"on_change": "set_dac_gain_Vout"
},
"DAC_VOLT_BUTTON": {
"description": "DAC volt",
"record_meta": true,
"initial": 1,
"value": [
"10000",
"25000",
"50000",
"60000"
],
"on_change": "cali_Vout"
},
"CTRL_HIGH_Z_15": {
"description": "ctrl highZ level",
"record_meta": true,
@@ -851,7 +901,8 @@
"initial": 0,
"value": [
"Iin",
"Vin"
"Vin",
"Vout"
]
},
"BLE_WRITE": {
@@ -912,11 +963,13 @@
"_notify(True)",
"set_adc_gain_I",
"set_adc_gain_Vin",
"set_dac_gain_Vout",
{
"expression": "ADC_DAC_CHANNEL_15",
"when": {
"0": "cali_Iin",
"1": "cali_Vin"
"1": "cali_Vin",
"2": "cali_Vout"
}
},
"_sync(True)",
@@ -1007,12 +1060,6 @@
"XE0;2B>va"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_adc_gain_I": {
"type": "RIS",
"data": [
@@ -1025,6 +1072,12 @@
"XE1;X01;B>ADC_LEVEL_V_IN_15"
]
},
"set_dac_gain_Vout": {
"type": "RIS",
"data": [
"XE1;X02;B>DAC_LEVEL_V_OUT_15"
]
},
"set_ctrl_highZ": {
"type": "RIS",
"data": [
@@ -1052,6 +1105,15 @@
"XF1;B>ADC_DAC_CHANNEL_15;B>ADC_LEVEL_V_IN_15"
]
},
"cali_Vout": {
"type": "RIS",
"parameter": {
"v": "DAC_VOLT_BUTTON"
},
"data": [
"XF1;B>ADC_DAC_CHANNEL_15;B>v"
]
},
"curve_iv": {
"type": "RIS",
"parameter": {
@@ -62,6 +62,7 @@
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"Dev Mode"
]
},
@@ -265,6 +266,17 @@
"expression": "VALUE"
}
},
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
@@ -295,20 +307,23 @@
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_I"
"1": "set_adc_gain_I",
"2": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
"1": "set_adc_gain_Vin",
"2": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3"
"1": "curve_cv3",
"2": "curve_const_vscan"
}
},
{
@@ -424,6 +439,23 @@
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1XD3;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"
@@ -62,6 +62,7 @@
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"Dev Mode"
]
},
@@ -265,6 +266,17 @@
"expression": "VALUE"
}
},
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
@@ -295,20 +307,23 @@
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_I"
"1": "set_adc_gain_I",
"2": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
"1": "set_adc_gain_Vin",
"2": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3"
"1": "curve_cv3",
"2": "curve_const_vscan"
}
},
{
@@ -424,6 +439,23 @@
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1XD3;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"
@@ -62,6 +62,7 @@
"value": [
"EIS CURVE",
"Cyclic Voltammetry",
"Chronoamperometric",
"Dev Mode"
]
},
@@ -265,6 +266,17 @@
"expression": "VALUE"
}
},
"VOLT_VSCAN": {
"description": "Voltage of VScan",
"record_meta": true,
"initial": 25000,
"domain": [
"VOLT_MAX"
],
"value": {
"expression": "VALUE"
}
},
"BLE_WRITE": {
"description": "send msg to elite",
"domain": {
@@ -295,20 +307,23 @@
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_I"
"1": "set_adc_gain_I",
"2": "set_adc_gain_I"
}
},
{
"expression": "MODE",
"when": {
"1": "set_adc_gain_Vin"
"1": "set_adc_gain_Vin",
"2": "set_adc_gain_Vin"
}
},
{
"expression": "MODE",
"when": {
"0": "curve_eis",
"1": "curve_cv3"
"1": "curve_cv3",
"2": "curve_const_vscan"
}
},
{
@@ -424,6 +439,23 @@
"1XD2;1X02;4B>ve;2B>vf;2B>cn"
]
},
"curve_const_vscan": {
"type": "RIS",
"parameter": {
"va": "VOLT_VSCAN",
"pa": "ADC_LEVEL_I_15",
"pb": "ADC_LEVEL_V_IN_15",
"pd": "CTRL_HIGH_Z_15",
"pe": "SAMPLE_RATE"
},
"data": [
"1XD3;",
"2B>va;",
"4b>pa;4b>pb;",
"4b>0;4b>pd;",
"2B>pe"
]
},
"ble_instru_send": [
"ble_write",
"_cdr('20X>ADC_VALUE_I')"