725 lines
26 KiB
Python
725 lines
26 KiB
Python
import os, time, csv, struct, sys
|
||
import numpy as np
|
||
sys.path.append(r'.\UserScripts')
|
||
from user_common import wordData2HexStr, nowStr, nowStr1, checkValue, params_to_int
|
||
from CRC import crc16 as checkValue
|
||
|
||
SENDHEADER = ''
|
||
RSPHEADER = ''
|
||
RETRYTIMES = 3
|
||
CYCLES = 1
|
||
TIMEOUT = 0.2
|
||
DEBUG = True
|
||
|
||
|
||
# 启动函数,命令开始会调用此函数
|
||
def start():
|
||
global recvData, deviceData
|
||
try:
|
||
log_i(f"[{devInfo['name']}] {cmdInfo['name']}".center(80, '-'))
|
||
|
||
deviceData = _G.get(f"{devInfo['name']}")
|
||
if not deviceData:
|
||
deviceData = {}
|
||
if 'data' not in deviceData:
|
||
deviceData['data'] = {}
|
||
if 'info' not in deviceData:
|
||
deviceData['info'] = {}
|
||
if 'status' not in deviceData:
|
||
deviceData['status'] = {}
|
||
if 'config' not in deviceData:
|
||
deviceData['config'] = {}
|
||
if 'channelsInfoTable' not in deviceData:
|
||
channelsInfoTable = {
|
||
'channel1':{
|
||
'name':'channel1',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0001,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x0020,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0030,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x0032,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0060,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0068,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0070,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0080,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0071,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0081,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel2':{
|
||
'name':'channel2',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0002,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x0022,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0034,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x0036,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0061,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0069,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0072,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0082,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0073,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0083,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel3':{
|
||
'name':'channel3',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0004,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x0024,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0038,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x003A,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0062,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006A,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0074,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0084,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0075,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0085,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel4':{
|
||
'name':'channel4',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0008,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x0026,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x003C,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x003E,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0063,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006B,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0076,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0086,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0077,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0087,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel5':{
|
||
'name':'channel5',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0010,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x0028,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0040,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x0042,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0064,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006C,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0078,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0088,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0079,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x0089,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel6':{
|
||
'name':'channel6',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0020,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x002A,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0044,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x0046,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0065,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006D,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007A,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008A,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007B,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008B,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel7':{
|
||
'name':'channel7',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0040,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x002C,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x0048,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x004A,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0066,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006E,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007C,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008C,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007D,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008D,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
},
|
||
'channel8':{
|
||
'name':'channel8',
|
||
'powerStatus':{
|
||
'value':0,
|
||
'address':0x0054,
|
||
'mask':0x0080,
|
||
'len':1
|
||
},
|
||
'signalVoltage':{
|
||
'value':1,
|
||
'address':0x002E,
|
||
'len':2
|
||
},
|
||
'powerCurrent':{
|
||
'value':1,
|
||
'address':0x004C,
|
||
'len':2
|
||
},
|
||
'powerVoltage':{
|
||
'value':1,
|
||
'address':0x004E,
|
||
'len':2
|
||
},
|
||
'signalVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x0067,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x006F,
|
||
'len':1
|
||
},
|
||
'unit':'uV'
|
||
},
|
||
'powerCurrentCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007E,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008E,
|
||
'len':1
|
||
},
|
||
'unit':'uA'
|
||
},
|
||
'powerVoltageCalibParams':{
|
||
'scale':{
|
||
'value':1,
|
||
'address':0x007F,
|
||
'len':1
|
||
},
|
||
'b':{
|
||
'value':0,
|
||
'address':0x008F,
|
||
'len':1
|
||
},
|
||
'unit':'mV',
|
||
}
|
||
}
|
||
}
|
||
deviceData['channelsInfoTable'] = channelsInfoTable
|
||
else:
|
||
channelsInfoTable = deviceData['channelsInfoTable']
|
||
deviceData['status']['StopAll'] = False
|
||
_G.set(devInfo['name'], deviceData)
|
||
|
||
except Exception as e:
|
||
log_e(f"Error in start. {str(e)}")
|
||
finish()
|
||
|
||
# 此函数会被重复调用,间隔10毫秒,直到finish()
|
||
def loop():
|
||
global recvData, deviceData
|
||
try:
|
||
read_device_info()
|
||
finish()
|
||
except Exception as e:
|
||
log_e(f"Error in loop. {str(e)}")
|
||
finish()
|
||
|
||
# 接收数据处理函数,当收到数据会调用此函数
|
||
def recvDataHandler(data):
|
||
global recvData
|
||
try:
|
||
recvData = recvData + data
|
||
except Exception as e:
|
||
log_e(f"Error in recvDataHandler. {str(e)}")
|
||
finish()
|
||
|
||
def log_du(str):
|
||
try:
|
||
deviceData = _G.get(f"{devInfo['name']}")
|
||
if (deviceData and 'config' in deviceData and 'flagDebug' in deviceData['config']):
|
||
debug = deviceData['config']['flagDebug']
|
||
else:
|
||
debug = False
|
||
if debug or DEBUG:
|
||
log_d(str)
|
||
except Exception as e:
|
||
raise Exception(f"Error in log_du(): {str(e)}")
|
||
|
||
def set_flagDebug(flag):
|
||
try:
|
||
deviceData = _G.get(f"{devInfo['name']}")
|
||
if not deviceData:
|
||
deviceData = {}
|
||
if 'config' not in deviceData:
|
||
deviceData['config'] = {}
|
||
deviceData['config']['flagDebug'] = flag
|
||
_G.set(devInfo['name'], deviceData)
|
||
return True
|
||
except Exception as e:
|
||
log_e(f"Error in set_flagDebug(): {str(e)}")
|
||
return False
|
||
|
||
def exeCmd(cmd):
|
||
try:
|
||
global recvData
|
||
data = bytearray().fromhex(cmd[0])
|
||
data += bytearray(checkValue(data).to_bytes(2, 'little'))
|
||
for i in range(RETRYTIMES):
|
||
log_du(f"[{nowStr()}] Sent:{wordData2HexStr(data)}")
|
||
recvData = bytearray()
|
||
send(data)
|
||
time.sleep(TIMEOUT)
|
||
rspLen = int(cmd[1])
|
||
if len(recvData) >= rspLen:
|
||
log_du(f"[{nowStr()}] Echo:{wordData2HexStr(recvData[0:rspLen])}")
|
||
crc = int.from_bytes(recvData[rspLen-2:rspLen], byteorder='little')
|
||
calc_value = checkValue(recvData[0:rspLen-2])
|
||
# log(f"{crc:04X}, {calc_value:04X}")
|
||
if crc == calc_value:
|
||
return [True, recvData[0:rspLen]]
|
||
return [False, None]
|
||
except Exception as e:
|
||
raise Exception(f"Error in exeCmd({cmd}): {str(e)}")
|
||
|
||
def read_registers(startAddress, count):
|
||
try:
|
||
ret = exeCmd([f"0103 {startAddress:04X} {count:04X}", count*2+6])
|
||
if ret[0]:
|
||
registers = {}
|
||
# log(str(ret[1]))
|
||
for i in range(count):
|
||
registers[f"0x{startAddress+i:04X}"] = ret[1][4+2*i]*256 + ret[1][4+2*i+1]
|
||
return [0, registers]
|
||
else:
|
||
return [-1, None]
|
||
except Exception as e:
|
||
raise Exception(f"Error in read_registers(): {str(e)}")
|
||
|
||
def update_dict_from_registers(dictData, registers):
|
||
try:
|
||
if not dictData or not registers:
|
||
return False
|
||
# log(str(dictData))
|
||
# log(str(registers))
|
||
for key, value in dictData.items():
|
||
# log(f"{str(key)}, {str(value)}")
|
||
if isinstance(value, dict):
|
||
if 'address' in value:
|
||
if f"0x{value['address']:04X}" in registers:
|
||
value['value'] = 0
|
||
for i in range(value['len']):
|
||
value['value'] = (value['value']<<16) + registers[f"0x{value['address']+i:04X}"]
|
||
# log(f"0x{value['address']+i:04X}")
|
||
# log(str(registers[f"0x{value['address']+i:04X}"]))
|
||
if 'mask' in value:
|
||
value['value'] = value['value'] & value['mask']
|
||
# if key == 'powerStatus':
|
||
# log(f"{value['value']}, {value['mask']}, {i}")
|
||
else:
|
||
update_dict_from_registers(value, registers)
|
||
else:
|
||
pass
|
||
# log(str(dictData))
|
||
return True
|
||
except Exception as e:
|
||
raise Exception(f"Error in update_dict_from_registers(): {str(e)}")
|
||
|
||
def read_device_info():
|
||
try:
|
||
deviceData = _G.get(f"{devInfo['name']}")
|
||
if not deviceData or 'channelsInfoTable' not in deviceData:
|
||
return False
|
||
else:
|
||
channelsInfoTable = deviceData['channelsInfoTable']
|
||
registers = {}
|
||
#读取0x0020~0x004F寄存器,并存为字典
|
||
registers1 = read_registers(0x0020, 0x0030)
|
||
registers2 = read_registers(0x0054, 0x0001)
|
||
#读取0x0060~0x008F寄存器,并存为字典
|
||
registers3 = read_registers(0x0060, 0x0020)
|
||
if registers1[0] == 0 and registers2[0] == 0 and registers3[0] == 0:
|
||
registers = {**registers1[1], **registers2[1], **registers3[1]}
|
||
log(str(registers))
|
||
#从寄存器数据字典中提取数据,存储至channelsInfoTable中
|
||
update_dict_from_registers(channelsInfoTable, registers)
|
||
deviceData['channelsInfoTable'] = channelsInfoTable
|
||
_G.set(devInfo['name'], deviceData)
|
||
log(str(deviceData))
|
||
|
||
#显示channelsInfoTable中的数据
|
||
except Exception as e:
|
||
log_e(f"Error in read_device_info(): {str(e)}")
|
||
return False
|
||
|
||
def write_registers_from_dict(dictData, registers):
|
||
try:
|
||
if not dictData or not registers:
|
||
return False
|
||
# log(str(dictData))
|
||
# log(str(registers))
|
||
for key, value in dictData.items():
|
||
# log(f"{str(key)}, {str(value)}")
|
||
if isinstance(value, dict):
|
||
if 'address' in value:
|
||
if f"0x{value['address']:04X}" in registers:
|
||
if 'mask' in value: #执行指令,读取当前配置,根据mask, 将要写入的位与当前配置做运算,再执行写配置指令
|
||
if value['len'] >= 1:
|
||
ret = exeCmd([f"0103 {value['address']:04X} {value['len']:04X}", 6+value['len']*2])
|
||
if ret[0]:
|
||
data = 0
|
||
for i in range(value['len']):
|
||
data = data<<16 + int(ret[1][4+2*i:6+2*i],16)
|
||
ret = exeCmd([f"0110 {value['address']:04X} {value['len']:04X} {data|value['mask']:0{value['len']*4}X}", 6+value['len']*2])
|
||
if not ret[0]:
|
||
raise Exception(f"fail to write registers({value['address']:04X}, {value['len']}).")
|
||
else:
|
||
raise Exception(f"fail to read registers({value['address']:04X}, {value['len']}).")
|
||
else:
|
||
raise Exception(f"len={str(value['len'])} is error. ")
|
||
else: #执行写入指令
|
||
if value['len'] >= 1:
|
||
ret = exeCmd([f"0110 {value['address']:04X} {value['len']:04X} {value['value']:0{value['len']*4}X}", 6+value['len']*2])
|
||
if not ret[0]:
|
||
raise Exception(f"fail to write registers({value['address']:04X}, {value['len']}).")
|
||
else:
|
||
raise Exception(f"len={str(value['len'])} is error. ")
|
||
else:
|
||
write_registers_from_dict(value, registers)
|
||
else:
|
||
pass
|
||
# log(str(dictData))
|
||
return True
|
||
except Exception as e:
|
||
raise Exception(f"Error in write_registers_from_dict(): {str(e)}") |