2022-02-07 20:27:30 +08:00
|
|
|
import sys
|
|
|
|
|
import json
|
|
|
|
|
import threading
|
2022-04-17 23:05:21 +08:00
|
|
|
|
2022-04-16 10:50:37 +08:00
|
|
|
from time import time, sleep
|
2022-02-12 00:21:27 +08:00
|
|
|
from datetime import datetime
|
2022-02-17 20:35:36 +08:00
|
|
|
from collections import deque
|
2022-04-17 23:05:21 +08:00
|
|
|
from copy import copy
|
|
|
|
|
from uuid import uuid4
|
|
|
|
|
|
|
|
|
|
from .task import Task
|
|
|
|
|
from .task_manager import TaskManager
|
|
|
|
|
from .instruction import Instruction
|
2022-02-25 20:54:58 +08:00
|
|
|
from biopro.device.manager import DeviceManager
|
|
|
|
|
from biopro.text import *
|
2022-04-16 10:50:37 +08:00
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
key_list = {
|
|
|
|
|
'deviceList': 'device',
|
|
|
|
|
}
|
2022-02-07 20:27:30 +08:00
|
|
|
|
|
|
|
|
class Project(threading.Thread):
|
2022-02-25 20:54:58 +08:00
|
|
|
def __init__(self, project, device_manager: DeviceManager, mqttThread = None, name="project"):
|
2022-02-07 20:27:30 +08:00
|
|
|
super(Project, self).__init__(name = name)
|
|
|
|
|
self._project = project
|
2022-02-25 20:54:58 +08:00
|
|
|
self._device_manager = device_manager
|
2022-02-07 20:27:30 +08:00
|
|
|
self._mqtt_thread = mqttThread
|
2022-08-19 15:44:51 +08:00
|
|
|
self._time_interval = 0.1
|
2022-02-12 00:21:27 +08:00
|
|
|
self._start_time = None
|
2022-04-17 23:05:21 +08:00
|
|
|
self._end_time = None
|
|
|
|
|
|
|
|
|
|
self._id = None
|
2022-05-04 18:07:05 +08:00
|
|
|
self._uuid = str(uuid4())
|
2022-04-17 23:05:21 +08:00
|
|
|
self._name = None
|
|
|
|
|
self._desc = None
|
|
|
|
|
self._device = None
|
|
|
|
|
self._complete_device = []
|
2022-05-04 18:07:05 +08:00
|
|
|
self._status = 0
|
2022-02-08 20:12:44 +08:00
|
|
|
|
2022-04-16 10:50:37 +08:00
|
|
|
self._instruction_set = Instruction()
|
2022-04-17 23:05:21 +08:00
|
|
|
self._stop_flag = False
|
|
|
|
|
|
2022-05-04 18:07:05 +08:00
|
|
|
self._task_manager = None
|
|
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
self.setup_project(project)
|
|
|
|
|
self.setup_device(self._device)
|
|
|
|
|
|
|
|
|
|
def setup_project(self, project):
|
|
|
|
|
for (key, value) in project.items():
|
|
|
|
|
if key in key_list.keys():
|
|
|
|
|
key = key_list[key]
|
|
|
|
|
|
2022-04-27 13:24:31 +08:00
|
|
|
if key == 'task':
|
|
|
|
|
self._task_manager = TaskManager(project['task'])
|
2022-05-04 18:07:05 +08:00
|
|
|
elif key == 'uuid':
|
|
|
|
|
pass
|
2022-04-17 23:05:21 +08:00
|
|
|
else:
|
|
|
|
|
setattr(self, key, value)
|
|
|
|
|
|
|
|
|
|
def setup_device(self, device_list):
|
|
|
|
|
for device in device_list:
|
|
|
|
|
complete_device = self._device_manager.get_device(device['connectDevice']['device_address'])
|
|
|
|
|
self._complete_device.append(complete_device)
|
2022-02-14 19:19:54 +08:00
|
|
|
|
2022-02-07 20:27:30 +08:00
|
|
|
@property
|
2022-04-17 23:05:21 +08:00
|
|
|
def id(self) -> int:
|
|
|
|
|
return self._id
|
|
|
|
|
|
|
|
|
|
@id.setter
|
|
|
|
|
def id(self, new_id):
|
|
|
|
|
self._id = new_id
|
2022-02-08 20:12:44 +08:00
|
|
|
|
|
|
|
|
@property
|
2022-04-17 23:05:21 +08:00
|
|
|
def uuid(self) -> str:
|
|
|
|
|
return self._uuid
|
|
|
|
|
|
|
|
|
|
@uuid.setter
|
|
|
|
|
def uuid(self, new_uuid):
|
|
|
|
|
self._uuid = new_uuid
|
2022-02-08 20:12:44 +08:00
|
|
|
|
|
|
|
|
@property
|
2022-04-17 23:05:21 +08:00
|
|
|
def name(self) -> str:
|
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
|
|
@name.setter
|
|
|
|
|
def name(self, new_name):
|
|
|
|
|
self._name = new_name
|
2022-02-07 20:27:30 +08:00
|
|
|
|
|
|
|
|
@property
|
2022-04-17 23:05:21 +08:00
|
|
|
def desc(self) -> str:
|
|
|
|
|
return self._desc
|
|
|
|
|
|
|
|
|
|
@desc.setter
|
|
|
|
|
def desc(self, new_desc):
|
|
|
|
|
self._desc = new_desc
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def status(self) -> str:
|
|
|
|
|
return self._status
|
|
|
|
|
|
|
|
|
|
@status.setter
|
|
|
|
|
def status(self, new_status):
|
|
|
|
|
self._status = new_status
|
2022-02-07 20:27:30 +08:00
|
|
|
|
|
|
|
|
@property
|
2022-04-17 23:05:21 +08:00
|
|
|
def device(self) -> list:
|
|
|
|
|
return self._device
|
|
|
|
|
|
|
|
|
|
@device.setter
|
|
|
|
|
def device(self, new_device):
|
|
|
|
|
self._device = new_device
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def task_list(self):
|
2022-05-04 18:07:05 +08:00
|
|
|
return self._task_manager.export_task_list
|
2022-03-02 18:13:02 +08:00
|
|
|
|
2022-04-18 01:52:52 +08:00
|
|
|
@property
|
|
|
|
|
def mqtt_thread(self):
|
|
|
|
|
return self._mqtt_thread
|
|
|
|
|
|
2022-09-06 16:28:38 +08:00
|
|
|
@property
|
|
|
|
|
def running_task(self):
|
|
|
|
|
return self._task_manager.running_task
|
|
|
|
|
|
2022-02-17 20:35:36 +08:00
|
|
|
def run(self):
|
2022-05-04 18:07:05 +08:00
|
|
|
self._status = 1
|
2022-04-16 10:50:37 +08:00
|
|
|
self._start_time = time()
|
2022-05-04 18:07:05 +08:00
|
|
|
self.mqtt_thread.broadcast_command('project:' + self._name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
|
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
while not self._stop_flag :
|
2022-04-16 10:50:37 +08:00
|
|
|
# check running task first
|
2022-04-08 11:17:07 +08:00
|
|
|
delay_time = 0
|
2022-04-16 10:50:37 +08:00
|
|
|
check_list = copy(self._task_manager.check_list)
|
2022-04-18 01:52:52 +08:00
|
|
|
|
2022-04-16 10:50:37 +08:00
|
|
|
for task in check_list:
|
2022-04-18 01:52:52 +08:00
|
|
|
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,
|
2022-08-16 11:34:47 +08:00
|
|
|
previous_task = self._task_manager.prev_task,
|
|
|
|
|
self_task = task
|
2022-04-18 01:52:52 +08:00
|
|
|
)
|
|
|
|
|
# print('match_condition_list', match_condition_list)
|
|
|
|
|
for condition in match_condition_list:
|
2022-08-19 15:44:51 +08:00
|
|
|
# print('\ncondition.type: ', condition.type)
|
2022-04-18 01:52:52 +08:00
|
|
|
match_action_list = task.get_match_action(condition.id)
|
2022-08-17 15:51:29 +08:00
|
|
|
# print('match_action_list', match_action_list)
|
2022-04-18 01:52:52 +08:00
|
|
|
for action in match_action_list:
|
2022-08-17 15:51:29 +08:00
|
|
|
# print('action type', action.type)
|
2022-08-19 15:44:51 +08:00
|
|
|
# print('match_action_list len: ', len(match_action_list))
|
2022-04-18 01:52:52 +08:00
|
|
|
if action.type == 'start' and task.status != 1:
|
|
|
|
|
self._task_manager.set_running_task(task)
|
2022-08-16 11:34:47 +08:00
|
|
|
# Trace
|
2022-04-18 01:52:52 +08:00
|
|
|
self.mqtt_thread.broadcast_command('project:task ' + task.name + ' start at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
2022-08-17 11:50:22 +08:00
|
|
|
elif action.type == 'cycle' and task.status != 1:
|
2022-08-18 17:39:59 +08:00
|
|
|
# TODO: directly goto next without swich cycle as running task
|
|
|
|
|
""" if task._cycle_count < task._cycle - 1:
|
|
|
|
|
task._cycle_count += 1
|
|
|
|
|
cycle_target = self._task_manager.task_list[task._cycle_next - 1] # TODO: not sure deep or shallow
|
|
|
|
|
cycle_target.reset()
|
|
|
|
|
task = cycle_target """
|
2022-08-17 11:50:22 +08:00
|
|
|
self._task_manager.set_running_task(task)
|
2022-08-17 15:51:29 +08:00
|
|
|
elif action.type == 'stop' and len(self._task_manager.running_task.parameter_set) == 0:
|
|
|
|
|
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()
|
2022-04-18 01:52:52 +08:00
|
|
|
|
2022-09-06 16:28:38 +08:00
|
|
|
elif action.type == 'idle':
|
|
|
|
|
self._task_manager.running_task.stop()
|
|
|
|
|
|
2022-04-18 01:52:52 +08:00
|
|
|
device = self._complete_device[action.target]
|
|
|
|
|
task_info = task.get_task_info(action)
|
|
|
|
|
instruction_set = getattr(self._instruction_set, action.type, None)
|
2022-08-19 15:44:51 +08:00
|
|
|
# print('instruction_set', instruction_set, '\n', action.type)
|
2022-08-17 15:51:29 +08:00
|
|
|
# if instruction_set != None and task.cycle == -1:
|
|
|
|
|
if instruction_set != None and len(task.parameter_set) > 0:
|
2022-04-18 01:52:52 +08:00
|
|
|
for instruction in instruction_set:
|
|
|
|
|
args = list(map(lambda arg: task_info[arg], instruction['arguments']))
|
|
|
|
|
threading.Thread(target=getattr(device, instruction['method'])(*args))
|
|
|
|
|
|
|
|
|
|
delay_time += (time() - now)
|
2022-04-16 10:50:37 +08:00
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
# check task not running then stop
|
|
|
|
|
if self.check_running_task_not_run() == True:
|
2022-08-17 11:50:22 +08:00
|
|
|
if self._task_manager.running_task.cycle == -1:
|
|
|
|
|
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])
|
2022-04-16 10:50:37 +08:00
|
|
|
self._task_manager.running_task.stop()
|
2022-09-06 16:28:38 +08:00
|
|
|
# self._task_manager.set_running_task(task)
|
2022-04-17 23:05:21 +08:00
|
|
|
|
|
|
|
|
# check project done then close project
|
2022-04-16 10:50:37 +08:00
|
|
|
if self.check_project_done() == True:
|
2022-04-18 01:52:52 +08:00
|
|
|
print('project stop at', datetime.now())
|
2022-04-16 10:50:37 +08:00
|
|
|
self.close()
|
2022-04-17 23:05:21 +08:00
|
|
|
|
|
|
|
|
if self._time_interval - delay_time > 0:
|
|
|
|
|
sleep(self._time_interval - delay_time)
|
|
|
|
|
|
|
|
|
|
def pause(self):
|
|
|
|
|
# TODO
|
|
|
|
|
pass
|
|
|
|
|
|
2022-05-04 18:07:05 +08:00
|
|
|
def stop(self):
|
|
|
|
|
self._task_manager.running_task.stop()
|
|
|
|
|
self.mqtt_thread.broadcast_command('project:task ' + str(self._task_manager.running_task.name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
|
|
|
|
self._status = 2
|
|
|
|
|
self._end_time = time()
|
|
|
|
|
self._stop_flag = True
|
|
|
|
|
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
|
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
def close(self):
|
2022-05-04 18:07:05 +08:00
|
|
|
self._status = 2
|
2022-04-17 23:05:21 +08:00
|
|
|
self._end_time = time()
|
|
|
|
|
self._stop_flag = True
|
2022-05-04 18:07:05 +08:00
|
|
|
self.mqtt_thread.broadcast_command('project:project ' + str(self._name) + ' stop at ' + datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
|
2022-04-17 23:05:21 +08:00
|
|
|
|
2022-04-16 10:50:37 +08:00
|
|
|
def check_project_done(self):
|
|
|
|
|
for task in self._task_manager.task_list:
|
2022-04-17 23:05:21 +08:00
|
|
|
# if task never start or still task is running then reject
|
2022-04-16 10:50:37 +08:00
|
|
|
if task.status == 1 or task.status == -1:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
2022-09-06 16:28:38 +08:00
|
|
|
def set_content(self, content):
|
|
|
|
|
self.running_task.button_trigger = True
|
|
|
|
|
|
2022-04-17 23:05:21 +08:00
|
|
|
def check_running_task_not_run(self):
|
2022-04-18 01:52:52 +08:00
|
|
|
# if no running task
|
|
|
|
|
if self._task_manager.running_task == None:
|
|
|
|
|
return False
|
2022-08-16 14:25:37 +08:00
|
|
|
|
|
|
|
|
for key in self._task_manager.running_task.action:
|
2022-08-17 15:51:29 +08:00
|
|
|
# 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':
|
2022-08-16 14:25:37 +08:00
|
|
|
return False
|
2022-09-06 16:28:38 +08:00
|
|
|
if len(self._task_manager.running_task.parameter_set) == 0 and self._task_manager.running_task.action[key]['type'] == 'idle':
|
|
|
|
|
return False
|
2022-08-16 14:25:37 +08:00
|
|
|
|
2022-05-04 18:07:05 +08:00
|
|
|
for device in self._task_manager.running_task.device:
|
2022-04-17 23:05:21 +08:00
|
|
|
if self._complete_device[device].status == 1:
|
2022-04-16 10:50:37 +08:00
|
|
|
return False
|
2022-04-17 23:05:21 +08:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def as_json(self):
|
2022-08-10 14:03:04 +08:00
|
|
|
running_task = None
|
|
|
|
|
if self._task_manager.running_task is not None:
|
|
|
|
|
running_task = self._task_manager.running_task.as_json()
|
2022-05-04 18:07:05 +08:00
|
|
|
data = {
|
2022-04-17 23:05:21 +08:00
|
|
|
'id': self._id,
|
|
|
|
|
'name': self._name,
|
|
|
|
|
'uuid': self._uuid,
|
|
|
|
|
'desc': self._desc,
|
|
|
|
|
'status': self._status,
|
|
|
|
|
'device': self._device,
|
2022-05-04 18:07:05 +08:00
|
|
|
'task': self.task_list,
|
2022-08-10 14:03:04 +08:00
|
|
|
'running_task': running_task
|
2022-04-17 23:05:21 +08:00
|
|
|
}
|
2022-05-04 18:07:05 +08:00
|
|
|
return data
|