import asyncio
import click
import subprocess
import sys
import ctypes
import time
import threading
import shlex
import re
import os
import readline
stop_thread = threading.Event()
'''
c struct
typedef struct PORTSTATUSINFO
{
char portName[64];
uint16_t linkStatus;
}T_PORTSTATUSINFO;
'''
class T_PORTSTATUSINFO(ctypes.Structure):
_fields_ = [
("portName",ctypes.c_char *64),
("linkStatus",ctypes.c_uint16)
]
#SFP_MEASURE_VALUE *measureValue
class SFP_MEASURE_VALUE(ctypes.Structure):
_fields_ = [
("temperature",ctypes.c_float),
("vcc",ctypes.c_float),
("txbias",ctypes.c_float),
("txpower",ctypes.c_float),
("rxpower",ctypes.c_float)
]
#SFP_ALARM *alarminfo
class SFP_ALARM(ctypes.Structure):
_fields_ = [
("sfp_temp_high_alarm",ctypes.c_uint32,1),
("sfp_temp_low_alarm",ctypes.c_uint32,1),
("sfp_vcc_high_alarm",ctypes.c_uint32,1),
("sfp_vcc_low_alarm",ctypes.c_uint32,1),
("sfp_tx_bias_high_alarm",ctypes.c_uint32,1),
("sfp_tx_bias_low_alarm",ctypes.c_uint32,1),
("sfp_tx_power_high_alarm",ctypes.c_uint32,1),
("sfp_tx_power_low_alarm",ctypes.c_uint32,1),
("sfp_rx_power_high_alarm",ctypes.c_uint32,1),
("sfp_rx_power_low_alarm",ctypes.c_uint32,1),
("sfp_tx_fault_alarm",ctypes.c_uint32,1),
("sfp_rx_los_alarm",ctypes.c_uint32,1),
("reserved",ctypes.c_uint32,20)
]
lib = ctypes.CDLL('/usr/lib/libfpga.so')
@click.group()
def cli():
pass
history_index = 0
history = []
def custom_completer(text,state):
commands = cli.commands
options = [cmd.name for cmd in commands.values() if cmd.name.startswith(text)]
if state < len(options):
return options[state]
else:
return None
readline.set_completer_delims('\t\n;')
readline.set_completer(custom_completer)
readline.parse_and_bind('tab: complete')
def get_user_input(user_input):
global history_index
char = user_input[0]
if char == '\x1b':
sequence = user_input[1]
if sequence == '[A':
if history_index > 0:
history_index -= 1
return history[history_index] if history else ''
elif sequence == '[B':
if history_index < len(history) - 1 :
history_index += 1
return history[history_index] if history else ''
elif sequence == '[C':
pass
elif sequence == '[D':
pass
else:
return sequence
elif char == '\n':
history.append(readline.get_line_buffer())
history.append(input)
history_index = len(history)
return user_input
elif char == '\t':
readline.insert_text(readline.get_completer().complete(readline.get_line_buffer()))
readline.redisplay()
else:
readline.insert_text(user_input)
return user_input
@cli.command()
@click.argument('input_file', type=click.Path(exists=True))
@click.argument('output_file', type=click.Path())
@click.option('--block-size', '-b', default=1024, help='Block size in bytes')
@click.option('--count', '-c', default=1, help='Number of blocks to copy')
def dd(input_file, output_file, block_size,count):
"""EMCC, SD read and write test commands."""
if count < 0:
count_arg = ''
else:
count_arg = 'count=' + str(count)
cmd = ['dd', 'if=' + input_file, 'of=' + output_file, 'bs=' + str(block_size), count_arg,'status=progress']
subprocess.run(cmd)
@cli.command()
@click.argument('help', default='')
def interrupt_count(help):
""" Interrupt count query command"""
try:
if help == "help":
click.echo("please input command [interrupt-count]")
else:
result = subprocess.run(['cat','/proc/interrupts'] , capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f"Error:{e}", err=True)
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--name','-n',type=str,help='port name value:[PORT_NMS1,PORT_NMS1,PORT_ETH1,...]')
def get_portState(hd,name):
'''EXI Ethernet Port Status Query Command'''
try:
if hd == 'help':
click.echo('=========================get-portstate=========================\n')
click.echo('Options:\n')
click.echo('\t -n,\t--name\t\t\tport name\n')
click.echo('Example:\n')
click.echo('get-portstate -n name\n')
click.echo('name = PORT_NMS ,PORT_NMS1 ,PORT_NMS2 ,PORT_ETH ,PORT_ETH1 ,PORT_ETH2\n')
else:
data = T_PORTSTATUSINFO()
data.portName = name.encode('utf-8')
data.linkStatus = 0xff
lib.get_portState.argtypes = [ctypes.POINTER(T_PORTSTATUSINFO)]
lib.get_portState.restype = ctypes.c_int
result = lib.get_portState(ctypes.byref(data))
if result != 0:
click.echo(f"Error: get-portState failed with error code {result}")
else:
if data.linkStatus == 0:
click.echo(f"port {name} port status is link down")
elif data.linkStatus == 1:
click.echo(f"port {name} port status is link up")
except Exception as e:
click.echo(f"Error:{e}")
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--id','-i',type=int,help='port name value:[1~8]')
def slot_present(hd,id):
'''Command to query the status of each board in place'''
try:
present =ctypes.c_bool()
present_ptr = ctypes.pointer(present)
if hd == 'help':
click.echo('=========================slot_present=======================\n')
click.echo('Options:\n')
click.echo('\t -i,\t--id\t\t\slot id\n')
click.echo('Example:\n')
click.echo('slot-present -i id\n')
click.echo('id = 1~8\n')
else:
lib.fpga_is_slot_present.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_bool)]
lib.fpga_is_slot_present.restype = ctypes.c_int
result = lib.fpga_is_slot_present(id,present_ptr)
if result != 0:
click.echo(f"Error: slot_present failed with error code {result}")
else:
if present:
click.echo(f"slot{id} is ON\n")
else:
click.echo(f"slot{id} is DOWN\n")
except Exception as e:
click.echo(f"Error:{e}")
def get_cu_temp(id):
'''get_cu_temp '''
try:
temp =ctypes.c_float()
temp_ptr = ctypes.pointer(temp)
lib.get_cu_temp.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_float)]
lib.get_cu_temp.restype = ctypes.c_int
result = lib.get_cu_temp(id,temp_ptr)
if result != 0:
click.echo(f"Error: get_cu_temp failed with error code {result}")
else:
pass
click.echo(f"cu temperature :" + str(temp.value) + "℃")
except Exception as e:
click.echo(f"Error:{e}")
def get_panel_temp():
'''get_panel_temp '''
try:
lib.cpld_enable_panel_temperature_output.argtypes = [ctypes.c_int]
lib.cpld_enable_panel_temperature_output.restype = ctypes.c_int
result = lib.cpld_enable_panel_temperature_output(1)
if result != 0:
click.echo(f"Error: get_panel_temp failed with error code {result}")
else:
pass
temp =ctypes.c_float()
temp_ptr = ctypes.pointer(temp)
lib.cpld_get_panel_board_temperature.argtypes = [ctypes.POINTER(ctypes.c_float)]
lib.cpld_get_panel_board_temperature.restype = ctypes.c_int
result = lib.cpld_get_panel_board_temperature(temp_ptr)
if result != 0:
click.echo(f"Error: get_panel_temp failed with error code {result}")
else:
pass
click.echo(f"panel temperature :" + str(temp.value) + "℃")
except Exception as e:
click.echo(f"Error:{e}")
def get_fan_temp(index):
'''get_fan_temp '''
try:
lib.cpld_enable_fan_temperature_output.argtypes = [ctypes.c_int,ctypes.c_int]
lib.cpld_enable_fan_temperature_output.restype = ctypes.c_int
result = lib.cpld_enable_fan_temperature_output(index,1)
if result != 0:
click.echo(f"Error: get_fan_temp failed with error code {result}")
else:
pass
temp =ctypes.c_float()
temp_ptr = ctypes.pointer(temp)
lib.cpld_get_fan_board_temperature.argtypes = [ctypes.c_int,ctypes.POINTER(ctypes.c_float)]
lib.cpld_get_fan_board_temperature.restype = ctypes.c_int
result = lib.cpld_get_fan_board_temperature(index,temp_ptr)
if result != 0:
click.echo(f"Error: get_fan_temp failed with error code {result}")
else:
pass
click.echo(f"fan tempeture :" + str(temp.value) + "℃")
except Exception as e:
click.echo(f"Error:{e}")
@cli.command()
@click.argument('card', type=str,default='')
@click.option('--id','-i',type=int,help='cu_41 : -i 0 ; cu_42 : -i 1')
def get_temp(card,id):
'''Temperature query command'''
try:
if card == 'help':
click.echo('=========================get_cu_temp=========================\n')
click.echo('Options:\n')
click.echo('\t -i,\t--id\t\t\tcu/fan/psu id\n')
click.echo('Example:\n')
click.echo('panel temp: get-temp panel \n')
click.echo('cu41 temp: get-temp cu -i 0 \n')
click.echo('cu42 temp: get-temp cu -i 1 \n')
click.echo('fan#1 temp: get-temp fan -i 1 \n')
click.echo('fan#2 temp: get-temp fan -i 2 \n')
click.echo('fan#3 temp: get-temp fan -i 3 \n')
click.echo('psu#1 temp: get-temp psu -i 1 \n')
click.echo('psu#2 temp: get-temp psu -i 2 \n')
elif card == 'panel':
get_panel_temp()
elif card == 'fan':
if id > 0 and id < 4:
get_fan_temp(id)
else:
click.echo('id :1~3')
elif card == 'cu':
if id == 0 or id == 1 :
get_cu_temp(id)
else:
click.echo('id :0~1')
elif card == 'psu':
if id == 1 or id == 2 :
result = subprocess.run(['/usr/bin/psu', str('-i'), str(id), str('-t')],capture_output=True, text=True, check=True)
result.stdout = result.stdout.replace("\n", "℃\n")
click.echo(result.stdout[len("===="):])
else:
click.echo('id :1~2')
else:
click.echo('Please input [panel,cu ,fan, psu]')
except Exception as e:
click.echo(f"Error:{e}")
@cli.command()
@click.argument('bus', type=str,default='')
@click.argument('obj', type=str,default='')
@click.argument('objfront', type=str,default='')
@click.argument('objbehind', type=str,default='')
@click.argument('opfront', type=str,default='')
@click.argument('opmiddle', type=str,default='')
@click.argument('opbehind', type=str,default='')
def mdio(bus,obj,objfront,objbehind,opfront,opmiddle,opbehind):
'''SMI read and write commands'''
try:
command=['/usr/bin/mdio']
if bus == 'help':
result = subprocess.run(['/usr/bin/mdio','-h'],capture_output=True, text=True, check=True)
else:
if bus != '':
command.append(bus)
if obj != '':
command.append(obj)
if objfront != '':
command.append(objfront)
if objbehind != '':
command.append(objbehind)
if opfront != '':
command.append(opfront)
if opmiddle != '':
command.append(opmiddle)
if opbehind != '':
command.append(opbehind)
result = subprocess.run(command,capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--version','-v','version', type=str, help='bus id',flag_value='-v')
@click.option('--iardtype','-i', type=str, help='device address',default='3')
@click.option('--ktype','-k', type=str, help='register address',default='3')
@click.option('--protect','-p','protect', type=str, help='num of register',flag_value='-p')
@click.option('--temperature','-t', 'temperature',type=str, help='register address bandwith',flag_value='-t')
@click.option('--file','-f','file', type=str, help='value',flag_value='-f')
@click.option('--alarm','-a','alarm', type=str, help='value',flag_value='-a')
@click.option('--manufacture','-m','manufacture', type=str, help='value',flag_value='-m')
@click.option('--read','-r','read', type=str, help='value',flag_value='-r')
def psu(hd,version,iardtype,ktype,protect,temperature,file,alarm,manufacture,read):
''' psu'''
try:
command=['/usr/bin/psu']
if version == '-v':
command.append('-v')
if iardtype != '3':
command.append('-i')
command.append(iardtype)
if ktype != '3':
command.append('-k')
command.append(ktype)
if protect == '-p':
command.append('-p')
if temperature == '-t':
command.append('-t')
if file == '-f':
command.append('-f')
if alarm == '-a':
command.append('-a')
if manufacture == '-m':
command.append('-m')
if read == '-r':
command.append('-r')
if hd == 'help':
result = subprocess.run(['/usr/bin/psu','--help'],capture_output=True, text=True, check=True)
else:
result = subprocess.run(command,capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('-w', 'opera', flag_value='-w')
@click.option('-r', 'opera', flag_value='-r')
@click.option('-g', 'opera', flag_value='-g')
@click.option('--slot','-s', type=str,help='slot id')
@click.option('--file','-f', type=click.Path(exists=True),help='filename')
@click.option('--offset','-o', type=str,help='offset')
@click.option('--length','-l', type=str,help='lenght')
def inventory(hd,opera,slot,file,offset,length):
'''EEPROM read and write commands. {panel|fan|cu|exi|psu}'''
try:
if hd == 'help':
result = subprocess.run(['/usr/bin/inventory', '--help'],capture_output=True, text=True, check=True)
elif opera.lower() == '-w':
if slot in ['cu41','cu42']:
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'), str('-a'),str('0x18') ,str('-v'), str('0x0')], capture_output=True, text=True, check=True)
result = subprocess.run(['/usr/bin/inventory', str('-w'), str('-s'),slot, str('-f'), file], capture_output=True, text=True, check=True)
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'), str('-a'), str('0x18'), str('-v') ,str('0x1')], capture_output=True, text=True, check=True)
elif slot == 'slot40' or slot == 'fan31' or slot == 'fan32' or slot == 'fan33':
address = '0x0c'
value = '0x1'
bus = '0x3'
if slot == 'slot40':
device = '0x60'
address = '0x04'
value = '0x10'
bus = '0x2'
elif slot == 'fan31':
device = '0x64'
elif slot == 'fan32':
device = '0x65'
elif slot == 'fan33':
device = '0x66'
result = subprocess.run(['/usr/bin/fpga_i2c', str('-w'), str('-b'), bus, str('-d'), device, str('-a'), address, str('-p'), str('2'), str('-v'), str('0x0')], capture_output=True, text=True, check=True)
result = subprocess.run(['/usr/bin/inventory', str('-w'), str('-s'), slot ,str('-f'), file], capture_output=True, text=True, check=True)
result = subprocess.run(['/usr/bin/fpga_i2c', str('-w'), str('-b'), bus, str('-d'), device ,str('-a') ,address, str('-p') ,str('2') ,str('-v'), value], capture_output=True, text=True, check=True)
elif slot == 'slot1~8':
'''line card, cpld_tool'''
pass
elif slot == 'slot0' or slot == 'psu21' or slot == 'psu22' or slot == 'mux1' or slot == 'mux2' or slot == 'mux3' or slot == 'mux4':
result = subprocess.run(['/usr/bin/inventory',str('-w'), str('-s'), slot ,str('-f'), file], capture_output=True, text=True, check=True)
elif opera.lower() == '-g':
result = subprocess.run(['/usr/bin/inventory',str('-g'),str('-s'), slot],capture_output=True, text=True, check=True)
elif opera.lower() == '-r':
result = subprocess.run(['/usr/bin/inventory',str('-r'),str('-s'), slot,str('-o'), offset,str('-l'),length],capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--bus','-b', type=str, help='bus id',default='')
@click.option('--device','-d', type=str, help='device address')
@click.option('--address','-a', type=str, help='register address')
@click.option('--num','-n', type=str, help='num of register',default='')
@click.option('--bandwidth','-p', type=str, help='register address bandwith',default='')
@click.option('-w', 'opera', flag_value='-w')
@click.option('-r', 'opera', flag_value='-r')
@click.option('--value','-v', type=str,multiple=True, help='value',default='')
def fpga_i2c(hd,bus,device,address,num,bandwidth,opera,value):
'''I2C read and write commands'''
try:
value_list = list(value)
command=['/usr/bin/fpga_i2c',str('-b'), bus, str('-d') ,device ,str('-a'), address ,str('-n'), num ,str('-p'), bandwidth, str(opera)]
if hd == 'help':
result = subprocess.run(['/usr/bin/fpga_i2c', str('--help')],capture_output=True, text=True, check=True)
elif opera == '-w':
for i in range(int(num)):
command += [str('-v'),value_list[int(i)]]
result = subprocess.run(command,capture_output=True, text=True, check=True)
elif opera == '-r':
result = subprocess.run(['/usr/bin/fpga_i2c',str('-b'), bus, str('-d') ,device ,str('-a'), address ,str('-n'), num ,str('-p'), bandwidth, str(opera)],capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--fan','-f', type=str, help='fan1 | fan2 | fan3',default='')
@click.option('--opera','-o', type=str, help='read/low/middle/height',default='')
def fan_speed(hd,fan,opera):
'''fan-speed'''
fan_address = ['0x64','0x65','0x66']
fan_id = ['fan1','fan2','fan3']
try:
if opera == 'read' :
result = subprocess.run(['/usr/bin/fpga_i2c', str('-b'), str('0x3'), str('-d'), str(fan_address[fan_id.index(fan)]), str('-a'), str('0x80'), str('-p') ,str('0x2') ,str('-n'), str('0x4') ,str('-r')],capture_output=True, text=True, check=True)
number = extract_and_convert_numbers(result.stdout)
speed =''
if number[6] == 91:
speed ='middle'
elif number[6] == 112:
speed ='low'
elif number[6] == 204:
speed ='height'
else:
speed = 'default'
print(f"fan speed is {speed} \n")
elif opera == 'middle':
command=['/usr/bin/fpga_i2c', str('-b'), str('0x3'), str('-d'), str(fan_address[fan_id.index(fan)]), str('-a'), \
str('0x80'), str('-p') ,str('0x2') ,str('-n'), str('0x4') ,str('-w'), str('-v') ,str('0x5b') ,str('-v'), str('0x8f'), str('-v') ,str('0xcc') ,str('-v') ,str('0xcc')]
result = subprocess.run(command,capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the fan middle-speed.\n")
elif opera == 'low':
command=['/usr/bin/fpga_i2c', str('-b'), str('0x3'), str('-d'), str(fan_address[fan_id.index(fan)]), str('-a'), \
str('0x80'), str('-p') ,str('0x2') ,str('-n'), str('0x4') ,str('-w'), str('-v') ,str('0x70') ,str('-v'), str('0x3d'), str('-v') ,str('0xcc') ,str('-v') ,str('0xcc')]
result = subprocess.run(command,capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the fan low-speed.\n")
elif opera == 'height':
command=['/usr/bin/fpga_i2c', str('-b'), str('0x3'), str('-d'), str(fan_address[fan_id.index(fan)]), str('-a'), \
str('0x80'), str('-p') ,str('0x2') ,str('-n'), str('0x4') ,str('-w'), str('-v') ,str('0xcc') ,str('-v'), str('0xcc'), str('-v') ,str('0xcc') ,str('-v') ,str('0xcc')]
result = subprocess.run(command,capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set fan height-speed.\n")
if hd == 'help':
print('please input fan-speed -f [fan1 | fan2 | fan3] -o [read | low | middle | height]')
except subprocess.CalledProcessError as e:
print(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('-w', 'opera', flag_value='-w')
@click.option('-r', 'opera', flag_value='-r')
@click.option('--address','-a', type=str, help='address')
@click.option('--num','-n', type=str, help='num of register',default='1')
@click.option('--value','-v', type=str, help='value',default='')
def fpga_tool(hd,opera,address,num,value):
''' reset sub card, CU main/backup, board in place'''
try:
if hd == 'help':
result = subprocess.run(['/usr/bin/fpga_tool', str('--help')],capture_output=True, text=True, check=True)
else:
result = subprocess.run(['/usr/bin/fpga_tool', str('-a') ,address, opera ,str('-n'),num,str('-v'),value],capture_output=True, text=True, check=True)
click.echo(result.stdout)
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('opera', type=str, default='')
def get_id(opera):
'''get_id'''
try:
if opera == 'help':
click.echo("please input command : get-id\n")
else:
result = subprocess.run(['/usr/bin/fpga_tool', str('-a') ,str('0x13'), str('-r') ,str('-n'),str('5')],capture_output=True, text=True, check=True)
name_id =['CU-SLOT-ID','SHELF-ID','HARDWARE-ID','PCB-ID','BOM-ID']
number = extract_and_convert_numbers(result.stdout)
max_length = max(len(str(index)) for index in number)
for index in range(5):
click.echo('\n\t' + name_id[index].ljust(15) + f':\t{str(hex(number[index+1])).ljust(max_length)}' +'\n')
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('opera', type=str, default='')
def watch_dog(opera):
'''cu watch_dog'''
try:
if opera == 'read' :
result = subprocess.run(['/usr/bin/fpga_tool', str('-a') ,str('0x0d'), str('-r')],capture_output=True, text=True, check=True)
number = extract_and_convert_numbers(result.stdout)
click.echo(f"watch dog is {'enable' if number[1] == 1 else 'disabled'} \n")
elif opera == 'enable':
result = subprocess.run(['/usr/bin/fpga_tool', str('-a') ,str('0x0d'), str('-w') ,str('-v'),str('1')],capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the watch-dog\n")
elif opera == 'disabled':
result = subprocess.run(['/usr/bin/fpga_tool', str('-a') ,str('0x0d'), str('-w') ,str('-v'),str('0')],capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the watch-dog\n")
else:
click.echo('please input watch-dog [read | enable | disabled ]')
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
async def exe_power(command):
process = await asyncio.create_subprocess_exec(
*command,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await process.communicate()
return stdout.decode()
async def on_or_off(slot_ads,pro_ads,op):
opera = [['0xa55a','0x14','0x50','0x1c','0x50','1'],#off
['0xa55a','0x10','0x50','0x18','0x50','1']]#on
commands = [
['/usr/bin/fpga_tool', '-w', '-a', str(pro_ads), '-v', opera[op][0]],
['/usr/bin/fpga_tool', '-w', '-a', str(slot_ads), '-v', opera[op][1]],
['/usr/bin/fpga_tool', '-w', '-a', str(slot_ads), '-v', opera[op][2]],
['/usr/bin/fpga_tool', '-w', '-a', str(slot_ads), '-v', opera[op][3]],
['/usr/bin/fpga_tool', '-w', '-a', str(slot_ads), '-v', opera[op][4]],
['/usr/bin/fpga_tool', '-r', '-a', str(slot_ads), '-n', opera[op][5]]
]
tasks = [exe_power(cmd) for cmd in commands]
results = await asyncio.gather(*tasks)
'''
for output in results:
print(output)
'''
@cli.command()
@click.argument('hd', type=str,default='')
@click.option('--slot','-s', type=str, help='slot1~slot8',default='')
@click.option('--opera','-o', type=str, help='put on/off',default='')
def card_power(hd,slot,opera):
'''card_power'''
try:
slot_id = ['slot1','slot2','slot3','slot4','slot5','slot6','slot7','slot8']
slot_address = ['0x61','0x62','0x63','0x64','0x65','0x66','0x67','0x68']
protect_address = ['0xc1','0xc2','0xc3','0xc4','0xc5','0xc6','0xc7','0xc8']
if opera == 'on' :
asyncio.run(on_or_off(slot_address[slot_id.index(slot)],
protect_address[slot_id.index(slot)],
1))
elif opera == 'off':
asyncio.run(on_or_off(slot_address[slot_id.index(slot)],
protect_address[slot_id.index(slot)],
0))
if hd == 'help':
click.echo('please input command: card-power -s [slot1~slot8] -o [on | off ]')
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('opera', type=str, default='')
def master_backup(opera):
'''master_backup'''
try:
if opera == 'read' :
result = subprocess.run(['/usr/bin/fpga_tool', str('-r'),str('-a'),str('0x0f')],capture_output=True, text=True, check=True)
number = extract_and_convert_numbers(result.stdout)
click.echo(f"cu status is {'master' if ((number[1] & 0x1) == 0) else 'backup'} \n")
elif opera == 'master':
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'),str('-a'),str('0x10') ,str('-v'), str('0x5')],capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the primary and backup status\n")
elif opera == 'backup':
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'),str('-a'),str("0x10") ,str('-v'), str('0x6')],capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the primary and backup status\n")
else:
click.echo('please input command: master-backup [read | master | backup ]')
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('opera', type=str, default='')
def reset_fan(opera):
'''reset_fan'''
try:
if opera =='':
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'),str('-a'),str("0x1f") ,str('-v'), str('0xa55a')],capture_output=True, text=True, check=True)
result = subprocess.run(['/usr/bin/fpga_tool', str('-w'),str('-a'),str("0x05") ,str('-v'), str('0x0')],capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("reset fan successfully\n")
else:
click.echo(' Execute command: [reset-fan] will reset three fans ')
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
@click.argument('hd', type=str, default='')
@click.option('-g', 'opera', flag_value='-g',default='')
@click.option('-s', 'opera', flag_value='-s',default='')
@click.option('--category','-c', type=str, help='present | LOS | DDM | las',default='')
@click.option('--val','-v', type=int)
def dump_eth(hd,opera,category,val):
'''dump_eth'''
try:
if hd == 'help':
click.echo('\nExample:')
click.echo('dump-eth -g -c [present | los | ddm | las]')
click.echo('dump-eth -s -c las -v [0 ~ 3]')
click.echo('\n0:ETH1 on, ETH2 on.')
click.echo('1:ETH1 off, ETH2 on.')
click.echo('2:ETH1 on, ETH2 off.')
click.echo('3:ETH1 off, ETH2 off.')
elif opera.lower() == '-g':
if category == 'present':
result = subprocess.run(['/usr/bin/fpga_i2c',str('-b'), str('2'), str('-d'), str('0x60'), str('-a') ,str('0xa4'), str('-p') ,str('0x2') ,str('-r')],capture_output=True, text=True, check=True)
number = extract_and_convert_numbers(result.stdout)
eth_mes_present_result(number[2])
elif category == 'ddm':
measureValue = SFP_MEASURE_VALUE()
lib.i2c_sfpReadMeasureValue.argtypes = [ctypes.c_uint8,ctypes.POINTER(SFP_MEASURE_VALUE)]
lib.i2c_sfpReadMeasureValue.restype = ctypes.c_int
measureValue_prt = ctypes.pointer(measureValue)
for i in range(2):
result = lib.i2c_sfpReadMeasureValue(i + 1, measureValue_prt)
if result == -1:
print(f"Error: eth_mes failed with error code {result}")
return -1
print(f"ETH{i + 1}\trxpower:{measureValue.rxpower:.3f}\ttxpower:{measureValue.txpower:.3f}")
elif category == 'los':
sfpalarm = SFP_ALARM()
lib.i2c_sfpReadAlarm.argtypes = [ctypes.c_uint8,ctypes.POINTER(SFP_ALARM)]
lib.i2c_sfpReadAlarm.restype = ctypes.c_int
sfpalarm_ptr = ctypes.pointer(sfpalarm)
for i in range(2):
result = lib.i2c_sfpReadAlarm(i + 1, sfpalarm_ptr)
if result == -1:
print(f"Error: eth_mes failed with error code {result}")
return 0
if sfpalarm.sfp_rx_los_alarm == 1:
print(f"ETH{i + 1} has rx_Los alarm.")
elif sfpalarm.sfp_rx_los_alarm == 0:
print(f"ETH{i + 1} has no rx_Los alarm.")
elif category == "las":
result = subprocess.run(['/usr/bin/fpga_i2c',str('-b'), str('0x2'), str('-d'), str('0x60'), str('-a') ,str('0xa5'), str('-p') ,str('0x2') ,str('-r')],capture_output=True, text=True, check=True)
number = extract_and_convert_numbers(result.stdout)
eth_mes_las_result(number[2])
else:
click.echo("please input [present | los | ddm | las]")
elif opera.lower() == '-s':
if category == 'las':
if val >= 0 and val < 4:
command=['/usr/bin/fpga_i2c', str('-w'), str('-b'), str(0x2), str('-d'), str('0x60'), str('-a'), str('0xa5'), str('-p'), str('2'), str('-v'), str(val)]
result = subprocess.run(command,capture_output=True, text=True, check=True)
index = result.stdout.lower().find("successfully")
if index !=-1:
click.echo("Successfully set the las\n")
else:
click.echo("please input value [0,4]")
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
@cli.command()
def exit():
"""Exit from current program."""
@cli.command()
def help():
"""Show help for all commands."""
commands = cli.commands
max_length = max(len(command.help) for command in commands.values())
click.echo(f"\nCommands available:\n")
for command in commands.values():
click.echo(f"{command.name.ljust(20)}\t\t\t{command.help.ljust(max_length)}")
def iio_result(process):
adc = []
ads = []
i=0
try:
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if 'raw value:' in output:
pattern = re.compile(r'raw value:\s*(\d+)')
num = pattern.findall(output)
if i<8:
adc.append(num[0])
else:
ads.append(num[0])
i += 1
click.echo("analysis result:\r\n")
click.echo("rk3568 adc\r\n")
i=0
multiple = 1
adc_result = [int(item)*1.8/1023 for item in adc]
for num in adc_result:
if i in [1,2,5,6,7]:
multiple = 2
else:
multiple = 1
click.echo(f"channels[{i}] {(num * multiple ):.3f}V\r\n")
i+=1
if os.path.exists('/sys/class/gpio/gpio23'):
result = subprocess.run(['sudo cat /sys/class/gpio/gpio23/value'],shell = True,stdout=subprocess.PIPE)
num = result.stdout.decode().strip()
click.echo(f"ads7959 {num}\r\n")
else:
click.echo("ads7959\r\n")
i=0
index = num
multiple = 1
ads_result = [int(item)*2.5/255 for item in ads]
for num in ads_result:
if index == '1':
if i == 0:
multiple = 2
else:
multiple = 1
elif index == '0':
if i == 0:
multiple = 3
elif i == 1:
multiple = 2
else:
multiple = 1
click.echo(f'channels[{i}] {(num * multiple):.3f}V\r\n')
i+=1
except subprocess.CalledProcessError as e:
click.echo(f'Error: {e}')
def gpio_switch(id):
result = subprocess.run(['sudo echo 23 > /sys/class/gpio/export'],shell = True,stdout=subprocess.PIPE)
result = subprocess.run(['sudo echo out > /sys/class/gpio/gpio23/direction'],shell = True,stdout=subprocess.PIPE)
result = subprocess.run([f'sudo echo {id} > /sys/class/gpio/gpio23/value'],shell = True,stdout=subprocess.PIPE)
def iio_output(process):
try:
iio_result(process)
if os.path.exists('/sys/class/gpio/gpio23'):
result = subprocess.run(['sudo echo 23 > /sys/class/gpio/unexport'],shell = True,stdout=subprocess.PIPE)
stop_thread.set()
#time.sleep(0.1)
except KeyboardInterrupt:
click.echo('Process interrupted by user')
stop_thread.set()
def direct_output(process):
try:
while not stop_thread.is_set():
output = process.stdout.readline()
if output == '' and process.poll() is not None:
stop_thread.set()
if 'error' in output.lower():
stop_thread.set()
if output:
click.echo(output, nl=False)
if 'input' in output:
usr_input = click.prompt("Input your selection ",type=str).strip()
process.stdin.write(usr_input + '\n')
process.stdin.flush()
sys.stdout.flush()
except KeyboardInterrupt:
click.echo('Process interrupted by user')
stop_thread.set()
@cli.command()
def iio_info():
"""Voltage measurement result query command."""
click.echo('\n')
def eth_mes_present_result(present):
if present == 0:
click.echo("ETH1: present, ETH2: present.\n")
elif present == 1:
click.echo("ETH1: absent, ETH2: present.\n")
elif present == 2:
click.echo("ETH1: present, ETH2: absent.\n")
elif present == 3:
click.echo("ETH1: absent, ETH2: absent.\n")
def eth_mes_las_result(present):
if present == 0:
click.echo("ETH1-las: on, ETH2-las: on.\n")
elif present == 1:
click.echo("ETH1-las: off, ETH2-las: on.\n")
elif present == 2:
click.echo("ETH1-las: on, ETH2-las: off.\n")
elif present == 3:
click.echo("ETH1-las: off, ETH2-las: off.\n")
@cli.command()
def cpld_upgrade():
"""CPLD Upgrade Command."""
click.echo('\n')
def extract_and_convert_numbers(s):
hex_numbers = re.findall(r'0x([0-9a-fA-F]+)', s)
numbers = []
for hex_num in hex_numbers:
try:
number = int(hex_num, 16)
numbers.append(number)
except ValueError:
print(f"Unable to convert hexadecimal numbers: {hex_num}")
return numbers
def execute_command(command_string):
from click.testing import CliRunner
runner = CliRunner()
result = runner.invoke(cli, command_string.split())
if result.exit_code == 0:
click.echo(result.output)
else:
click.echo(f'Error: {result.output}')
def run_command(command_args):
try:
if "cpld-upgrade" in command_args or \
"iio-info" in command_args:
cmd = shlex.split(command_args)
stop_thread.clear()
if 'cpld-upgrade' in command_args:
replaced_string = command_args.replace("cpld-upgrade", "/usr/bin/cpld_upgrade")
elif 'iio-info' in command_args:
if 'ads7959' in command_args:
gpio_switch(cmd[2])
command_args = command_args.replace(f"ads7959","")
command_args = command_args.replace(cmd[2],"")
replaced_string = command_args.replace("iio-info", "/usr/bin/iio_info")
if 'help' in replaced_string:
replaced_string = replaced_string.replace("help", "--help")
command_args = shlex.split(replaced_string)
process = subprocess.Popen(
command_args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True,
)
if '/usr/bin/iio_info' in process.args and '--help' not in process.args :
output_thread = threading.Thread(target=iio_output, args=(process,))
output_thread.start()
else:
output_thread = threading.Thread(target=direct_output, args=(process,))
output_thread.start()
if stop_thread.is_set():
output_thread.join()
if process.poll() is None:
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
click.echo('Child process timed out, forced termination.')
process.kill()
process.stdout.close()
process.stderr.close()
process.stdin.close()
process.communicate()
click.echo('\r\n')
elif command_args == '':
pass
else:
execute_command(command_args)
except Exception as e:
click.echo(f'Exception: {str(e)}')
def interactive_mode():
stop_thread.set()
user_input = ''
while True:
while stop_thread.is_set():
user_input = input('>>>: ')
if user_input.lower() == 'exit':
click.echo('Exiting Interactive CLI. Goodbye!')
break
elif user_input.lower() == '':
pass
else:
run_command(user_input)
if user_input.lower() == 'exit':
break
if __name__ == '__main__':
interactive_mode()
cli最新版本
于 2024-10-28 18:10:14 首次发布