#!/usr/bin/python """ A minimal utility to send structured commands to the BPS board using Java BPS network utility """ import sys import os sys.path.insert(0, '../codegen') import commands from utils import mls from analogvariables import * from bpsentities.descriptors import PayloadFieldEnum, PayloadFieldU8, PayloadFieldU16, PayloadFieldU32 from commutils import * import os ASK_CONFIRM = False SHOW_SENT_DATA = True SHOW_RECEIVED_DATA = False CLB_IPADDR = '172.21.1.221' JSCRIPTFMT = './execute.sh BPSCmd {} [REQCODE] [RESPCODE] [RESPLEN] [REQPAYLOAD]'.format(CLB_IPADDR) channel2current_MON_5V_I = analogvariables.convert_chn2meas_PWB_I def ask_confirm(): answer = "" while answer not in ["y", "n"]: answer = raw_input("Confirm [Y/N]? ").lower() return answer == "y" def mydirtyexec(_cmd): # like it dirty... os.system(_cmd + ' > __tmp') return open('__tmp', 'r').read() def getconvertedvals(command, fields): vals = list() # the pork way (with great respect for porks) if command.name == 'SENSOR_GET_SINGLE': vn = fields[0] converter = None if vn == 'MON_DUL_BOARDTEMP': converter = convert_chn2meas_DUL_BOARDTEMP units = 'C' elif vn == 'MON_TEMP2': converter = convert_chn2meas_TEMP2 units = 'C' elif vn == 'MON_TEMP1': converter = convert_chn2meas_TEMP1 units = 'C' elif vn == 'MON_VEOC_RTN_I': converter = convert_chn2meas_VEOC_RTN_I units = 'A' elif vn == 'MON_VEOC_FWR_I': converter = convert_chn2meas_VEOC_FWR_I units = 'A' elif vn == 'MON_HYDRO_I': converter = convert_chn2meas_HYDRO_I units = 'mA' elif vn == 'MON_INPUT_V': converter = convert_chn2meas_INPUT_V units = 'V' elif vn == 'MON_LBL_I': converter = convert_chn2meas_LBL_I units = 'mA' elif vn == 'MON_GLRA_I': converter = convert_chn2meas_GLRA_I units = 'A' elif vn == 'MON_GLRB_I': converter = convert_chn2meas_GLRB_I units = 'A' elif vn == 'MON_PWB_I': converter = convert_chn2meas_PWB_I units = 'A' elif vn == 'FLAG_DUL_ALARMPOS1': pass elif vn == 'FLAG_DUL_ALARMPOS2': pass elif vn == 'FLAG_DUL_ALARMNEG1': pass elif vn == 'FLAG_DUL_ALARMNEG2': pass elif vn == 'FLAG_HYDRO_PWR_FAULT': pass elif vn == 'FLAG_LBL_PWR_FAULT': pass elif vn == 'FLAG_GLRA_FAULT': pass elif vn == 'FLAG_GLRB_FAULT': pass elif vn == 'FLAG_POWERBOARD_FAULT': pass elif vn == 'FLAG_GLRA_GOOD': pass elif vn == 'FLAG_GLRB_GOOD': pass elif vn == 'FLAG_POWERBOARD_GOOD': pass else: pass if converter: vals.append(['','']) vals.append([converter(fields[1]), units]) # VALUE vals.append([converter(fields[2]), units]) # OFFSET vals.append([converter(fields[3]), units]) # MAXVALUE vals.append([converter(fields[4]), units]) # MEANVALUE else: # to be verified pass elif command.name in ['SENSOR_VALUES_GETALL', 'SENSOR_AVERAGE_GETALL', 'SENSOR_OFFSETS_GETALL', 'SENSOR_MAXVALUES_GETALL']: vals.append([convert_chn2meas_DUL_BOARDTEMP(fields[0]), '']) # FIELD 0 : MON_DUL_BOARDTEMP_MEAN vals.append([convert_chn2meas_TEMP2(fields[1]), '']) # FIELD 1 : MON_TEMP2_MEAN vals.append([convert_chn2meas_TEMP1(fields[2]), '']) # FIELD 2 : MON_TEMP1_MEAN vals.append([convert_chn2meas_VEOC_RTN_I(fields[3]), '']) # FIELD 3 : MON_VEOC_RTN_I_MEAN vals.append([convert_chn2meas_VEOC_FWR_I(fields[4]), '']) # FIELD 4 : MON_VEOC_FWR_I_MEAN vals.append([convert_chn2meas_HYDRO_I(fields[5]), '']) # FIELD 5 : MON_HYDRO_I_MEAN vals.append([convert_chn2meas_INPUT_V(fields[6]), '']) # FIELD 6 : MON_INPUT_V_MEAN vals.append([convert_chn2meas_LBL_I(fields[7]), '']) # FIELD 7 : MON_LBL_I_MEAN vals.append([convert_chn2meas_GLRA_I(fields[8]), '']) # FIELD 8 : MON_GLRA_I_MEAN vals.append([convert_chn2meas_GLRB_I(fields[9]), '']) # FIELD 9 : MON_GLRB_I_MEAN vals.append([convert_chn2meas_PWB_I(fields[10]), '']) # FIELD 10 : MON_PWB_I_MEAN return vals def getconvertedvals___OLD(command, fields): vals = list() # the pork way (with great respect for porks) if command.name == 'SENSOR_GET_SINGLE': vn = fields[0] converter = None if vn == 'MON_5V_I': converter = channel2current_MON_5V_I units = 'A' elif vn in ['MON_LBL_I', 'MON_HYDRO_I']: converter = channel2current_12V units = 'A' elif vn in ['MON_DU_I', 'MON_DU_IRTN']: converter = channel2current_MON_DU_I units = 'A' elif vn == 'MON_BPS_V': converter = channel2voltage_MON_BPS_V units = 'V' elif vn == 'MON_THEATSINK': converter = channel2temperature_THEATSINK units = 'V (A.U.)' elif vn == 'MON_TBOARD': converter = channel2temperature_TBOARD units = 'C' else: pass if converter: vals.append(['','']) vals.append([converter(fields[1]), units]) # VALUE vals.append([converter(fields[2]), units]) # OFFSET vals.append([converter(fields[3]), units]) # MAXVALUE vals.append([converter(fields[4]), units]) # MEANVALUE elif command.name in ['SENSOR_VALUES_GETALL', 'SENSOR_AVERAGE_GETALL', 'SENSOR_OFFSETS_GETALL', 'SENSOR_MAXVALUES_GETALL']: vals.append([channel2current_MON_5V_I(fields[0]), 'A']) # MON_5V_I_MEAN vals.append([channel2current_12V(fields[1]), 'A']) # MON_LBL_I_MEAN vals.append([channel2current_MON_DU_I(fields[2]), 'A']) # MON_DU_I_MEAN vals.append([channel2current_MON_DU_I(fields[3]), 'A']) # MON_DU_IRTN_MEAN vals.append([channel2voltage_MON_BPS_V(fields[4]), 'V']) # MON_BPS_V_MEAN vals.append([channel2current_12V(fields[5]), 'A']) # MON_HYDRO_I_MEAN vals.append([channel2temperature_THEATSINK(fields[6]), 'V (A.U.)']) # MON_THEATSINK_MEAN vals.append([channel2temperature_TBOARD(fields[7]), 'C']) # MON_TBOARD_MEAN return vals if __name__ == '__main__': # command line options # example # python sendcommand.py COMMAND_NAME payload0 payload1 ... # COMMAND_NAME is the human readable name of the command (e.g.: ) # redirect stdout to null in order to avoid the warnings during object creation stdout = sys.stdout f = open(os.devnull, 'w') sys.stdout = f switch_list = commands.SwitchList() analog_variable_list = commands.AnalogVariableList() digital_variable_list = commands.DigitalVariableList() user_pin_list = commands.UserPinList() commands = commands.CommandList(switch_list, analog_variable_list, digital_variable_list, user_pin_list) # restore normal stdout sys.stdout = stdout if len(sys.argv) <= 1: print "Command code missing" sys.exit(0) command_name = sys.argv[1].upper() filtered_commands = [command for command in commands.entries() if command.name.startswith(command_name)] if len(filtered_commands) == 0: print 'No command found with name starting with: "{}"'.format(command_name) elif len(filtered_commands) != 1: print 'More than one command found with name starting with: "{}":'.format(command_name) for command in filtered_commands: print ' {}'.format(command.name) sys.exit(0) # get the wanted command command = filtered_commands[0] # expected number of request fields: req_field_count = len(command.request_payload) if len(sys.argv) != req_field_count + 2: print 'Number of request payload fields not correct. The {} command expects {} fields; {} where given.'.format(command.name, len(command.request_payload), len(sys.argv) - 2) sys.exit(0) # prepare the payload payload_data = list() payload_field_values = list() idx = 2 for field in command.request_payload: val = int(sys.argv[idx]) payload_field_values.append(val) if isinstance(field, PayloadFieldU8): assert val < 2**8, 'Too big value for uint8' payload_data.append(val) elif isinstance(field, PayloadFieldU16): assert val < 2 ** 16, 'Too big value for uint16' payload_data.append((val >> 8) & 0xff) payload_data.append(val & 0xff) elif isinstance(field, PayloadFieldU32): assert val < 2 ** 32, 'Too big value for uint32' payload_data.append((val >> 24) & 0xff) payload_data.append((val >> 16) & 0xff) payload_data.append((val >> 8) & 0xff) payload_data.append(val & 0xff) elif isinstance(field, PayloadFieldEnum): assert val < 2 ** 8, 'Too big value for enum' payload_data.append(val) else: assert False, 'Unmanaged type {}'.format(field.__class__.__name__) idx += 1 print "Sending packet:" print ' Command code: {} (raw data: {})'.format(command.name, command.request_code) # print ' Payload data: {} (raw data: {})'.format(payload_field_values, payload_data) print ' Request payload:' idx = 0 for field in command.request_payload: print ' {} = {}'.format(field.name, payload_field_values[idx]) idx += 1 if ASK_CONFIRM: if not ask_confirm(): print "Operation aborted by user" sys.exit() jcmd = JSCRIPTFMT jcmd = jcmd.replace('[REQCODE]', str(command.request_code)) jcmd = jcmd.replace('[RESPCODE]', str(command.response_code)) jcmd = jcmd.replace('[RESPLEN]', str(2 * command.get_response_payload_len())) if not payload_data: jcmd = jcmd.replace('[REQPAYLOAD]', 'null') else: pl = '' for b in payload_data: # print b.__class__ n0, n1 = uint8_to_nibbles(b) pl += chr(n1) pl += chr(n0) jcmd = jcmd.replace('[REQPAYLOAD]', pl) print 'Executing command: "{}"'.format(jcmd) r = mydirtyexec(jcmd) print 'Response:"{}"'.format(r.strip()) # convert nibbles to bytes payload_bytes = list() for k in range(0, len(r)-1, 2): d = 16 * int(r[k], 16) + int(r[k+1], 16) payload_bytes.append(d) print "Received packet:" # print ' Command code: {}'.format(command_code) # print ' Payload data: {} (raw data: {})'.format(payload_field_values, payload_data) print ' Response payload:' byte_idx = 0 rawvalues = list(); for field in command.response_payload: value = -1 if isinstance(field, PayloadFieldU8): value = payload_bytes[byte_idx] rawvalues.append(value) byte_idx += 1 elif isinstance(field, PayloadFieldU16): value = payload_bytes[byte_idx] << 8 value += payload_bytes[byte_idx+1] rawvalues.append(value) byte_idx += 2 elif isinstance(field, PayloadFieldU32): value = payload_bytes[byte_idx] << 24 value += payload_bytes[byte_idx+1] << 16 value += payload_bytes[byte_idx+2] << 8 value += payload_bytes[byte_idx+3] rawvalues.append(value) byte_idx += 4 elif isinstance(field, PayloadFieldEnum): value = field.get_value_by_index(payload_bytes[byte_idx]) rawvalues.append(value) byte_idx += 1 else: assert False, 'Unmanaged type {}'.format(field.__class__.__name__) convertedvals = getconvertedvals(command, rawvalues) field_idx = 0 for field in command.response_payload: s = ' {} = {} '.format(field.name, rawvalues[field_idx]) if convertedvals: if convertedvals[field_idx][0]: s += '({:0.3} {})'.format(convertedvals[field_idx][0], convertedvals[field_idx][1]) print s field_idx += 1