import multiprocessing as mp import re import typing from multiprocessing.connection import Connection import peewee from pubsub import pub from Agreement.FQ.skio.define import CmdType, KCommand, KReply, IVar from Agreement.FQ.skio.exception import SkError from Agreement.FQ.skio.worker.service import SkWorkerProcess from Agreement.FQ.skio.worker.state import SlotInfo, find_variable from utils.WorkModels import init_database, PointModel class SkIO(object): connection: Connection def __init__(self): _connection, self.connection = mp.Pipe() self.worker = SkWorkerProcess(_connection) def cmd(self, cmd: KCommand) -> KReply: self.worker.query.put(cmd) replay = self.connection.recv() if replay.type == CmdType.ERROR: if isinstance(replay.body, SkError): raise SkError(replay.body.errno, replay.body.msg) raise SkError(msg=str(replay.body)) return replay def setup(self, path): if self.worker and not self.worker.is_alive(): self.worker.start() self.cmd(KCommand(CmdType.SETUP, body=path)) database = peewee.SqliteDatabase(path.joinpath('etc', 'skio.db')) init_database(database) pub.sendMessage('SKIO.SETUP', a=path) def ping(self) -> typing.List[SlotInfo]: pong = self.cmd(KCommand(CmdType.PING)) return pong.body def read(self, name, value=None, remote=True, force=False, **kwargs): # su 点不支持同时查询多个点,下面是check 5ESFAC/RPCxxx=xxx(CHx) channel_val = None if value: val_re = re.search('\(\S+(\d+)\)', str(value)) if val_re: kwargs['proc_val'] = value # read_txs_time 获取通道 channel_val = val_re.groups()[0] # 用来兼容读多个TX elif 'TX' in str(value).upper(): kwargs['proc_val'] = value reply = self.cmd( KCommand(CmdType.READ, body={'name': name, 'remote': remote, 'force': force, 'kwargs': kwargs})) # need_time = 'need_time' in kwargs need_time = kwargs.pop('need_time', False) v = self.find(name, value) name = v.name if need_time: ti = self.read_txs_time(name, channel_val) else: # 时间为 -1 的时候,前端不显示 ti = -1 if reply.type == CmdType.SUCCESS: return reply.body, ti def write(self, name, value, force=False, **kwargs): val_re = re.search('(\d+(\.\d+)?)\(', str(value)) if val_re: kwargs['proc_val'] = value # 浮点数 if val_re.groups()[1]: value = float(val_re.groups()[0]) else: value = int(val_re.groups()[0]) reply = self.cmd(KCommand(CmdType.WRITE, body={'name': name, 'value': value, 'force': force, 'kwargs': kwargs})) need_time = 'need_time' in kwargs ti = 0 if need_time else -1 if reply.type == CmdType.SUCCESS: return reply.body, ti def incr(self, name, value): old_value = self.read(name) value += old_value self.write(name, value) def is_ready(self): return self.worker.is_alive() def txsPy(self, path): """ 执行 TXS 初始化脚本 :param path: :return: """ reply = self.cmd(KCommand(CmdType.TXSPY, path)) if reply.type == CmdType.SUCCESS: return True return False def read_txs_time(self, name, channel_val=None) -> float: """ 返回时间,不用设置通道 :param name: :return: """ # 如果传进来的是通道名 print('read_txs_time', name, channel_val) if channel_val: channel_val = int(channel_val) pxi_freg = PointModel.filter(PointModel.sig_name == name).first() rpc, in_or_out = pxi_freg.uri.split(':') # 获得计时卡 pxi_time: PointModel = PointModel.filter(PointModel.sig_name == f'{rpc}_{channel_val}_TIME').first() else: pxi_freg = PointModel.filter(PointModel.sig_name == name).first() rpc, in_or_out = pxi_freg.uri.split(':') if re.search(r'(\d+)', in_or_out): in_or_out_value = re.search(r'(\d+)', in_or_out).groups()[0] in_or_out_value = int(in_or_out_value) # channel_val = 1 # 获得计时卡 pxi_time: PointModel = PointModel.filter(PointModel.sig_name == f'{rpc}_{in_or_out_value}_TIME').first() time_reply = self.cmd( KCommand(CmdType.READ, body={'name': pxi_time.sig_name, 'remote': True, 'force': False})) if time_reply.type == CmdType.SUCCESS: return time_reply.body def find(self, name: str, value='', **kwargs) -> IVar: try: kwargs.setdefault('proc_val', f'{value}') return find_variable(name, **kwargs) except Exception: return None def clear_all_refer_time(self): print('>>> 清空参考信号') # 取到所有参考信号 for i in range(1, 9): self.write(f'__SYS.REFER_{i}', 0) print('>>> 清空RPC和ESFAC时间') for i in range(1, 5): for j in range(1, 5): self.write(f'RPC{i}_{j}_TIME', '-1') # TODO: 需要把ESFAC时间清空 for i in range(1, 6): self.write(f'ESFAC_A_{i}_TIME', '-1') for i in range(1, 6): self.write(f'ESFAC_B_{i}_TIME', '-1') for i in range(1, 6): self.write(f'ESFAC_DAS_{i}_TIME', '-1') # 在规程执行完清除所有通道 def clear_all_channel(self): print('>>> 清空所有channel') for i in range(1, 5): for j in range(1, 3): self.write(f'RPC{i}_{j}_CHANNEL', 0) for i in range(1, 6): self.write(f'ESFAC_A_{i}_CHANNEL', 0) for i in range(1, 6): self.write(f'ESFAC_B_{i}_CHANNEL', 0)