TG-PlatformPlus/command.py

381 lines
13 KiB
Python

#!/opt/homebrew/bin/python3
# -*- coding:utf-8 -*-
from PyQt6.QtCore import QThread, pyqtSignal, QMutex
from logs import log
import json
from influxDB import influxdb
from ser import myserial
from environment import env
import matplotlib
from matplotlib import pyplot
import numpy
from globals import _G
class Command(QThread):
logMsg = pyqtSignal(str)
runOver = pyqtSignal()
mutex = QMutex()
def __init__(self, port=myserial, name='', cmdValue='', payload='', rspLen=0, timeout=1000, extAtt = ''):
super().__init__()
self.port = port
self.cmdInfo = {}
self.setCmdData(name, cmdValue, payload, rspLen, timeout, extAtt)
self.namespace = {}
self.namespace['tsdb'] = influxdb
self.namespace['matplotlib'] = matplotlib
self.namespace['plot'] = pyplot
self.namespace['numpy'] = numpy
self.updateNamespace()
def setCmdData(self, name = '', cmdValue = '', payload = '', rspLen = 0, timeout = 1000, extAtt = ''):
if isinstance(cmdValue, str):
try:
self.cmdInfo['cmdValue'] = bytearray().fromhex(cmdValue)
except:
self.cmdInfo['cmdValue'] = bytearray()
log.error('illeagle cmd str')
else:
self.cmdInfo['cmdValue'] = cmdValue
if isinstance(payload, str):
try:
self.cmdInfo['payload'] = bytearray().fromhex(payload)
except:
self.cmdInfo['payload'] = bytearray()
log.error('illeagle cmd data str')
else:
self.cmdInfo['payload'] = payload
self.cmdInfo['name'] = name
self.cmdInfo['rspLen'] = rspLen
self.cmdInfo['timeout'] = timeout
self.cmdInfo['extAtt'] = {}
if extAtt:
try:
self.cmdInfo['extAtt'] = json.loads(extAtt)
except:
self.cmdInfo['extAtt'] = {}
def updateNamespace(self):
self.namespace['cmdInfo'] = self.cmdInfo
self.namespace['env'] = env.toDict()
def setScript(self, script):
self.script = script
def setSendingCheckScript(self, script):
self.sendingCheckScript = script
def setRecvingCheckScript(self, script):
self.recvingCheckScript = script
def setSendingCodecScript(self, script):
self.sendingCodecScript = script
def setRecvingCodecScript(self, script):
self.recvingCodecScript = script
def __scriptSendingCheck(self, data):
if not hasattr(self, 'sendingCheckScript'):
return data
if not isinstance(self.sendingCheckScript, str):
return data
if len(self.sendingCheckScript) == 0:
return data
namespace = {}
exec(self.sendingCheckScript, namespace)
try:
ret = namespace['check_value'](data)
if ret:
chsm = bytearray((int(ret)).to_bytes(2, byteorder='big'))
log.debug('sendingCheckScript ret :', ret, ' ', chsm.hex(' '))
return data + chsm
except:
log.error('failed to exec function -> sendingCheckScript')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '发送校验脚本执行出错')
return data
def __scriptRecvingCheck(self, data):
if not hasattr(self, 'recvingCheckScript'):
return True
if not isinstance(self.recvingCheckScript, str):
return True
if len(self.recvingCheckScript) == 0:
return True
namespace = {}
exec(self.recvingCheckScript, namespace)
try:
ret = namespace['check'](data)
log.debug('recv check: ', ret)
return ret
except:
log.error('failed to exec function -> recvingCheckScript')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '接收校验脚本执行出错')
return False
def __scriptSendingCodec(self, data):
if not hasattr(self, 'sendingCodecScript'):
return data
if not isinstance(self.sendingCodecScript, str):
return data
if len(self.sendingCodecScript) == 0:
return data
namespace = {}
exec(self.sendingCodecScript, namespace)
try:
ret = namespace['encode'](data)
if ret:
log.debug('sendingCodecScript ret :', ret.hex(' '))
return ret
except:
log.error('failed to exec function -> sendingCheckScript')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '发送编码脚本执行出错')
return data
def __scriptEncodeLen(self, dataLen):
if not hasattr(self, 'sendingCodecScript'):
return dataLen
if not isinstance(self.sendingCodecScript, str):
return dataLen
if len(self.sendingCodecScript) == 0:
return dataLen
namespace = {}
exec(self.sendingCodecScript, namespace)
try:
ret = namespace['encodeLen'](dataLen)
if ret:
return ret
except:
log.error('failed to exec function -> encodeLen')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '计算编码长度失败')
return dataLen
def __scriptRecvingCodec(self, data):
if not hasattr(self, 'recvingCodecScript'):
return data
if not isinstance(self.recvingCodecScript, str):
return data
if len(self.recvingCodecScript) == 0:
return data
namespace = {}
exec(self.recvingCodecScript, namespace)
try:
ret = namespace['decode'](data)
if ret:
log.debug('recvingCodecScript ret :', ret.hex(' '))
return ret
except:
log.error('failed to exec function -> recvingCodecScript')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '接收解码脚本执行出错')
return data
#发送数据校验之前回调函数
def __scriptTxCbBeforeChecking(self, txData):
if self.namespace['txCbBeforeChecking'] == None:
return txData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['txCbBeforeChecking'](txData)
log.debug('txCbBeforeChecking ret :', ret.hex(' '))
if ok:
txData = ret
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
except:
log.error('failed to exec function -> txCbBeforeChecking')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '发送数据校验之前回调函数执行失败')
return txData
#发送数据编码之前回调函数
def __scriptTxCbBeforeCodingAfterChecking(self, txData):
if self.namespace['txCbBeforeCodingAfterChecking'] == None:
return txData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['txCbBeforeCodingAfterChecking'](txData)
log.debug('txCbBeforeCodingAfterChecking ret :', ret.hex(' '))
if ok:
txData = ret
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
except:
log.error('failed to exec function -> txCbBeforeCodingAfterChecking')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '发送数据编码之前回调函数执行失败')
return txData
#发送数据之前回调函数
def __scriptTxCbBeforeSendingAfterCoding(self, txData):
if self.namespace['txCbBeforeSendingAfterCoding'] == None:
return txData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['txCbBeforeSendingAfterCoding'](txData)
log.debug('txCbBeforeSendingAfterCoding ret :', ret.hex(' '))
if ok:
txData = ret
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
except:
log.error('failed to exec function -> txCbBeforeSendingAfterCoding')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '发送数据之前回调函数执行失败')
return txData
#收到指令数据后解码之前回调函数
def __scriptRxCbAfterReceivingBeforeDecoding(self, rxData):
if self.namespace['rxCbAfterReceivingBeforeDecoding'] == None:
return rxData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['rxCbAfterReceivingBeforeDecoding'](rxData)
log.debug('rxCbAfterReceivingBeforeDecoding ret :', ret.hex(' '))
if ok:
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
return ret
except:
log.error('failed to exec function -> rxCbAfterReceivingBeforeDecoding')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '收到指令数据后解码之前回调函数执行失败')
return rxData
#指令数据解码之后校验之前回调函数
def __scriptRxCbAfterDecoingBeforeChecking(self, rxData):
if self.namespace['rxCbAfterDecoingBeforeChecking'] == None:
return rxData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['rxCbAfterDecoingBeforeChecking'](rxData)
log.debug('rxCbAfterDecoingBeforeChecking ret :', ret.hex(' '))
if ok:
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
return ret
except:
log.error('failed to exec function -> rxCbAfterDecoingBeforeChecking')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '指令数据解码之后校验之前回调函数执行失败')
return rxData
#指令数据校验之后回调函数
def __scriptRxCbAfterChecking(self, rxData):
if self.namespace['rxCbAfterChecking'] == None:
return rxData
try:
self.updateNamespace()
ok, ret, msg = self.namespace['rxCbAfterChecking'](rxData)
log.debug('rxCbAfterChecking ret :', ret.hex(' '))
if ok:
if isinstance(msg, str) and len(msg) > 0:
self.logMsg.emit(msg)
return ret
except:
log.error('failed to exec function -> rxCbAfterChecking')
self.logMsg.emit('指令' + self.cmdInfo['name'] + '指令数据校验之后回调函数执行失败')
return rxData
def run(self):
try:
Command.mutex.lock()
self.namespace['_G'] = _G #第一次赋值,此处不可去掉
self.namespace['txCbBeforeChecking'] = None
self.namespace['txCbBeforeCodingAfterChecking'] = None
self.namespace['txCbBeforeSendingAfterCoding'] = None
self.namespace['rxCbAfterReceivingBeforeDecoding'] = None
self.namespace['rxCbAfterDecoingBeforeChecking'] = None
self.namespace['rxCbAfterChecking'] = None
exec(self.script, self.namespace)
ba = bytearray(b'')
if (len(bytearray(self.cmdInfo['cmdValue'])) != 0):
ba = ba + bytearray(self.cmdInfo['cmdValue'])
if (len(bytearray(self.cmdInfo['payload'])) != 0):
ba = ba + bytearray(self.cmdInfo['payload'])
if len(ba) == 0:
log.warning('no cmd data to send, return')
return
txBa = self.__scriptTxCbBeforeChecking(ba)
txBa = self.__scriptSendingCheck(txBa)
txBa = self.__scriptTxCbBeforeCodingAfterChecking(txBa)
txBa = self.__scriptSendingCodec(txBa)
txBa = self.__scriptTxCbBeforeSendingAfterCoding(txBa)
self.cmdInfo['txPacket'] = txBa
ok, rxBa = self.port.sendCmd(
txBa,
self.__scriptEncodeLen(self.cmdInfo['rspLen']),
self.cmdInfo['timeout']
)
self.cmdInfo['rxPacket'] = rxBa
rxBa = self.__scriptRxCbAfterReceivingBeforeDecoding(rxBa)
if len(rxBa) != 0:
rxBa = self.__scriptRecvingCodec(rxBa)
self.cmdInfo['rxPacketDecoded'] = rxBa
rxBa = self.__scriptRxCbAfterDecoingBeforeChecking(rxBa)
if len(rxBa) == 0:
self.cmdInfo['rxPacketCheckOk'] = None
else:
self.cmdInfo['rxPacketCheckOk'] = self.__scriptRecvingCheck(rxBa)
rxBa = self.__scriptRxCbAfterChecking(rxBa)
log.debug('cmd exec over:', self.cmdInfo['name'], ' ', ok)
if ok == -1:
self.logMsg.emit('指令无应答或者应答长度不足')
self.runOver.emit()
except Exception as e:
log.error(e)
self.logMsg.emit(f'脚本错误: {e}')
finally:
Command.mutex.unlock()