server/udp/podCommands.js - from node.js /JavaScript to Python (object)


In [1]:
# find out where we are on the file directory
import os, sys

In [2]:
print( os.getcwd())
print( os.listdir(os.getcwd()))


/home/topolo/PropD/servetheloop/packetDef
['.ipynb_checkpoints', 'reactGS', 'podCommands.ipynb', 'podCommandparams.pkl', 'react-GS_node_to_py_to_YAML.ipynb']

The reactGS folder "mimics" the actual react-groundstation github repository, only copying the file directory structure, but the source code itself (which is a lot) isn't completely copied over. I wanted to keep these scripts/notebooks/files built on top of that github repository to be separate from the actual working code.


In [3]:
wherepodCommandsis = os.getcwd()+'/reactGS/server/udp/' 
print(wherepodCommandsis)


/home/topolo/PropD/servetheloop/packetDef/reactGS/server/udp/

node.js/(JavaScript) to json; i.e.

node.js/(JavaScript) $\to$ json

Make a copy of server/udp/podCommands.js.

In this copy, comment out var chalk = require('chalk') (this is the only thing you have to do manually).

Run this in the directory containing your copy of podCommands.js:

node traverse_podCommands.js

This should generate a json file podCmds_lst.json

Available podCommands as a Python list; json to Python list, i.e. json $\to$ Python list


In [4]:
import json

In [5]:
f_podCmds_json = open(wherepodCommandsis+'podCmds_lst.json','rb')
rawjson_podCmds = f_podCmds_json.read()
f_podCmds_json.close()

In [6]:
print(type(rawjson_podCmds))
podCmds_lst=json.loads(rawjson_podCmds)
print(type(podCmds_lst))
print(len(podCmds_lst)) # there are 104 available commands for the pod!


<type 'str'>
<type 'list'>
104

In [7]:
for cmd in podCmds_lst: 
    print cmd


GS_Heartbeat
LGU_PositionChange
LGU_SpeedChange
FCUPod_Off
FCUPod_Stop
FCUPod_PowerLatch
setBrakeDevelopmentMode
FCUBrake_DisableDevelopmentMode
FCUBrake_EnableDevelopmentMode
FCUBrake_MoveMotorRAW
FCUBrake_MoveMotorIBeam
FCUBrake_BeginInit
FCUBrake_MLPSetZeroLeftBrake
FCUBrake_MLPSetZeroRightBrake
FCUBrake_MLPSetSpanLeftBrake
FCUBrake_MLPSetSpanRightBrake
FCUStepper_SetMaxAngularAccel
FCUStepper_SetPicoMetersPerRev
FCUStepper_SetMaxRPM
FCUStepper_SetMicroStepResolution
FCUBrake_RequestDevelopmentMode
FCUStreamingControlStart_AccelCalData
FCUStreamingControlStart_AccelFullData
FCUStreamingControlStop_Accel
FCUStreamingControlStart_Brakes
FCUStreamingControlStart_MotorsRaw
FCUStreamingControlStart_Lasers
FCUStreamingControlStart_ForwardLaser
FCUAccel_FineZero
FCUAccel_AutoZero
FCUContrast_StartStream
FCUContrast_StopStream
PowerAStopAllManualDischarging
PowerBStopAllManualDischarging
PowerAPowerLatch
PowerBPowerLatch
PowerAChargeRelayOff
PowerAChargeRelayOn
PowerAStreamingOff
PowerBStreamingOff
PowerAStreamCurrentTemps
PowerBStreamCurrentTemps
PowerAStreamTempLocations
PowerBStreamTempLocations
PowerARequestRomID
PowerBRequestRomID
PowerAStartCharging
PowerAStopCharging
PowerBStartCharging
PowerBStopCharging
PowerAStartDischarging
PowerAStopDischarging
PowerBStartDischarging
PowerBStopDischarging
PowerARequestBMS
PowerBRequestBMS
PowerARequestCooling
PowerAStartCooling
PowerBRequestCooling
PowerBStartCooling
PowerAStartRepressurizing
PowerBStartRepressurizing
PowerATestSolenoidPin4
PowerATestSolenoidPin8
PowerATestSolenoidPin16
PowerATestSolenoidPin22
PowerATestSolenoidPin23
PowerBTestSolenoidPin4
PowerBTestSolenoidPin8
PowerBTestSolenoidPin16
PowerBTestSolenoidPin22
PowerBTestSolenoidPin23
PowerAToPowerB
PowerBToPowerA
PodSafePowerNodeA
PodSafePowerNodeB
ForcePreRunPhase
FCUHover_Enable
FCUHover_Disable
FCUHover_EnableStaticHovering
FCUHover_ReleaseStaticHovering
FCUHover_EnableHEX
FCUHover_DisableHEX
FCUHover_SetHEXSpeed
FCUHover_StartCooling
FCUHover_StopCooling
FCUHover_OpenSolenoid
FCUAuxProp_Enable
FCUAuxProp_Disable
FCUAuxProp_SetSpeed
FCUGimbal_Static
FCUGimbal_FullBackwards
XilinxSim_Start
XilinxSim_Stop
XilinxSim_Laser0On
XilinxSim_Laser0Off
XilinxSim_Laser1On
XilinxSim_Laser1Off
XilinxSim_Laser2On
XilinxSim_Laser2Off
AutoSequenceTest_Start
AutoSequenceTest_Skip
AutoSequenceTest_Kill
AutoSequenceTest_Restart

Dirty parsing of podCommands.js and the flight control parameters


In [8]:
f_podCmds = open(wherepodCommandsis+'podCommands.js','rb')
raw_podCmds = f_podCmds.read()
f_podCmds.close()
print(type(raw_podCmds))
print(len(raw_podCmds))


<type 'str'>
19296

In [13]:
# get the name of the functions
cmdnameslst = [func[:func.find("(")].strip() for func in raw_podCmds.split("function ")]

In [23]:
funcparamslst = [func[func.find("(")+1:func.find(")")] 
                     if func[func.find("(")+1:func.find(")")] is not '' else None for func in raw_podCmds.split("function ")]
#raw_podCmds.split("function ")[3][ raw_podCmds.split("function ")[3].find("(")+1:raw_podCmds.split("function ")[3].find(")")]

In [46]:
# more parsing of this list of strings  
funcparamslst_cleaned = []
for param in funcparamslst:
    if param is None:
        funcparamslst_cleaned.append(None)
    else:
        funcparamslst_cleaned.append( param.strip().split(',') )

In [38]:
print(len(raw_podCmds.split("function ")) ) # 106 commands

# get the index value (e.g. starts at position 22) of where "udp.tx.transmitPodCommand" starts, treating it as a string
#whereisudptransmit = [func.find("udp.tx.transmitPodCommand(") for func in raw_podCmds.split("function ")]

whereisudptransmit = []
for func in raw_podCmds.split("function "):
    val = func.find("udp.tx.transmitPodCommand(")
    if val is not -1:
        if func.find("// ",val-4) is not -1 or func.find("// udp",val-4) is not -1:
            whereisudptransmit.append(None)
        else:
            whereisudptransmit.append(val)
    else: 
        whereisudptransmit.append(None)

#whereisudptransmit = [func.find("udp.tx.transmitPodCommand(") for func in raw_podCmds.split("function ")]


# remove -1 values
#whereisudptransmit = filter(lambda x : x != -1, whereisudptransmit)

rawParams=[funcstr[ funcstr.find("(",val)+1:funcstr.find(")",val)]  if val is not None else None for funcstr, val in zip(raw_podCmds.split("function "), whereisudptransmit)]


106

In [47]:
funcparamslst_cleaned[:10]


Out[47]:
[["'./binary'"],
 ['udp'],
 None,
 ['liftName', ' liftDirection'],
 ['liftName', ' liftSpeed'],
 ['value'],
 None,
 None,
 ['data'],
 None]

In [32]:
raw_podCmds.split("function ")[4].find("// ",116-4);


Out[32]:
113

In [42]:
# more parsing of this list of strings
cleaningParams = []
for rawparam in rawParams: 
    if rawparam is None:
        cleaningParams.append(None)
    else:
        cleanParam = []
        cleanParam.append( rawparam.split(',')[0].strip("'") )
        for strval in rawparam.split(',')[1:]:
            strval2 = strval.strip()
            try: 
                strval2 = int(strval2,16)
                strval2 = hex(strval2)
            except ValueError:
                strval2
            cleanParam.append(strval2)
        cleaningParams.append(cleanParam)

In [43]:
cleaningParams[:10]


Out[43]:
[None,
 None,
 ['Flight Control', '0x400', '0x0', '0x0', '0x0', '0x0'],
 None,
 None,
 None,
 ['Flight Control', '0x3000', '0x76543210', '0x0', '0x0', '0x0'],
 ['Flight Control', '0x1', '0x1234abcd', '0x0', '0x0', '0x0'],
 ['Flight Control', '0x3030', '0xabcd1245', 'data.powerNode', '0x0', '0x0'],
 ['Flight Control', '0x1400', '0x0', '0x0', '0x0', '0x0']]

In [12]:
# get the name of the functions

#[func[:func.find("(")]  
#    if func.find("()") is not -1 else None for func in raw_podCmds.split("function ")];
cmdnameslst = [func[:func.find("(")].strip() for func in raw_podCmds.split("function ")]

In [48]:
# each node js function has its arguments; do that first
podfunclst = zip(cmdnameslst, funcparamslst_cleaned)
print(len(podfunclst))


106

In [50]:
podfunclst[:10];

In [51]:
# each node js function has its arguments; do that first
podCommandparams = zip(podfunclst, cleaningParams)
print(len(podCommandparams))


106

In [52]:
podCommandparams[-2]


Out[52]:
(('PodSafePowerNodeB', None),
 ['Power Node B', '0x3000', '0x76543210', '0x0', '0x0', '0x0'])

So the structure of our result is as follows:

Python tuples (each of size 2 for each of the tuples)
"""
( (Name of pod command as a string, None if there are no function parameters or Python list of function arguments),
Python list [ Subsystem name as a string, paramter1 as a hex value, paramter2 as a hex value, paramter3 as a hex value, paramter4 as a hex value] )
"""

Notice that in the original code, there's some TO DO's still left (eek!) so that those udp.tx.transmitPodCommand is commented out or left as TODO, and some are dependent upon arguments in the function (and thus will change, the parameter is a variable).


In [53]:
podCommandparams[:10]


Out[53]:
[(('const bin = require', ["'./binary'"]), None),
 (('', ['udp']), None),
 (('GS_Heartbeat', None),
  ['Flight Control', '0x400', '0x0', '0x0', '0x0', '0x0']),
 (('LGU_PositionChange', ['liftName', ' liftDirection']), None),
 (('LGU_SpeedChange', ['liftName', ' liftSpeed']), None),
 (('setBrakeDevelopmentMode', ['value']), None),
 (('FCUPod_Off', None),
  ['Flight Control', '0x3000', '0x76543210', '0x0', '0x0', '0x0']),
 (('FCUPod_Stop', None),
  ['Flight Control', '0x1', '0x1234abcd', '0x0', '0x0', '0x0']),
 (('FCUPod_PowerLatch', ['data']),
  ['Flight Control', '0x3030', '0xabcd1245', 'data.powerNode', '0x0', '0x0']),
 (('FCUBrake_DisableDevelopmentMode', None),
  ['Flight Control', '0x1400', '0x0', '0x0', '0x0', '0x0'])]

In [54]:
try:
    import CPickle as pickle
except ImportError:
    import pickle

In [55]:
podCommandparamsfile = open("podCommandparams.pkl",'wb')
pickle.dump( podCommandparams , podCommandparamsfile )
podCommandparamsfile.close()

In [56]:
# open up a pickle file like so:
podCommandparamsfile_recover = open("podCommandparams.pkl",'rb')
podCommandparams_recover = pickle.load(podCommandparamsfile_recover)
podCommandparamsfile_recover.close()

In [57]:
podCommandparams_recover[:10]


Out[57]:
[(('const bin = require', ["'./binary'"]), None),
 (('', ['udp']), None),
 (('GS_Heartbeat', None),
  ['Flight Control', '0x400', '0x0', '0x0', '0x0', '0x0']),
 (('LGU_PositionChange', ['liftName', ' liftDirection']), None),
 (('LGU_SpeedChange', ['liftName', ' liftSpeed']), None),
 (('setBrakeDevelopmentMode', ['value']), None),
 (('FCUPod_Off', None),
  ['Flight Control', '0x3000', '0x76543210', '0x0', '0x0', '0x0']),
 (('FCUPod_Stop', None),
  ['Flight Control', '0x1', '0x1234abcd', '0x0', '0x0', '0x0']),
 (('FCUPod_PowerLatch', ['data']),
  ['Flight Control', '0x3030', '0xabcd1245', 'data.powerNode', '0x0', '0x0']),
 (('FCUBrake_DisableDevelopmentMode', None),
  ['Flight Control', '0x1400', '0x0', '0x0', '0x0', '0x0'])]

Going to .csv

@nuttwerx and @ernestyalumni decided upon separating the multiple entries in a field by the semicolon ";":


In [79]:
tocsv = []
for cmd in podCommandparams_recover:
    name = cmd[0][0]
    funcparam = cmd[0][1]
    if funcparam is None:
        fparam = None
    else:
        fparam = ";".join(funcparam)
    udpparam = cmd[1]
    if udpparam is None:
        uname  = None
        uparam = None
    else:
        uname = udpparam[0]
        uparam = ";".join( udpparam[1:] )
    tocsv.append([name,fparam,uname,uparam])

Add the headers in manually:

1 = Command name; 2 = Function args; 3 = Pod Node; 4 = Command Args


In [80]:
header = ["Command name","Function args", "Pod Node", "Command Args"]
tocsv.insert(0,header)

The csv fields format is as follows:

(function name) , (function arguments (None is there are none)) , (UDP transmit name (None is there are no udp transmit command)), (UDP transmit parameters, 4 of them, separated by semicolon, or None if there are no udp transmit command )


In [69]:
import csv

In [82]:
f_podCommands_tocsv = open("podCommands.csv",'w')
tocsv_writer = csv.writer( f_podCommands_tocsv )
tocsv_writer.writerows(tocsv)
f_podCommands_tocsv.close()

In [77]:
#tocsv.insert(0,header) no need

In [83]:
#tocsv[:10] no need

In [ ]: