Moved GSE dictionaries to deployment directory, moved Gse binaries to Gds/tkGui/bin

This commit is contained in:
Timothy Canham 2019-03-19 22:08:17 -07:00
parent 33c39c94a0
commit e74f575ae7
31 changed files with 1305 additions and 695 deletions

3
.gitignore vendored
View File

@ -61,3 +61,6 @@ core
*TopologyAppAi_IDTableLog.txt
.vscode
py_dict
.settings

View File

@ -290,7 +290,7 @@ def generate_topology(the_parsed_topology_xml, xml_filename, opt):
# Hack to set up deployment path for instanced dictionaries (if one exists remove old one)
#
if opt.default_topology_dict:
os.environ["DICT_DIR"] = os.environ.get("FPRIME_CORE_DIR", BUILD_ROOT) + os.sep + "Gse/generated" + os.sep + DEPLOYMENT
os.environ["DICT_DIR"] = os.environ.get("FPRIME_CORE_DIR", BUILD_ROOT) + os.sep + DEPLOYMENT + os.sep + "py_dict"
dict_dir = os.environ["DICT_DIR"]
PRINT.info("Removing old instanced topology dictionaries in: %s", dict_dir)
import shutil

View File

@ -8,25 +8,25 @@ XML Source: ${source}
'''
# Import the types this way so they do not need prefixing for execution.
from fprime.gse.models.serialize.type_exceptions import *
from fprime.gse.models.serialize.type_base import *
from fprime.common.models.serialize.type_exceptions import *
from fprime.common.models.serialize.type_base import *
from fprime.gse.models.serialize.bool_type import *
from fprime.gse.models.serialize.enum_type import *
from fprime.gse.models.serialize.f32_type import *
from fprime.gse.models.serialize.f64_type import *
from fprime.common.models.serialize.bool_type import *
from fprime.common.models.serialize.enum_type import *
from fprime.common.models.serialize.f32_type import *
from fprime.common.models.serialize.f64_type import *
from fprime.gse.models.serialize.u8_type import *
from fprime.gse.models.serialize.u16_type import *
from fprime.gse.models.serialize.u32_type import *
from fprime.gse.models.serialize.u64_type import *
from fprime.common.models.serialize.u8_type import *
from fprime.common.models.serialize.u16_type import *
from fprime.common.models.serialize.u32_type import *
from fprime.common.models.serialize.u64_type import *
from fprime.gse.models.serialize.i8_type import *
from fprime.gse.models.serialize.i16_type import *
from fprime.gse.models.serialize.i32_type import *
from fprime.gse.models.serialize.i64_type import *
from fprime.common.models.serialize.i8_type import *
from fprime.common.models.serialize.i16_type import *
from fprime.common.models.serialize.i32_type import *
from fprime.common.models.serialize.i64_type import *
from fprime.gse.models.serialize.string_type import *
from fprime.gse.models.serialize.serializable_type import *
from fprime.common.models.serialize.string_type import *
from fprime.common.models.serialize.serializable_type import *
from fprime.gse.models.common import channel_telemetry
from fprime.common.models.common import channel_telemetry

View File

@ -8,25 +8,25 @@ XML Source: ${source}
'''
# Import the types this way so they do not need prefixing for execution.
from fprime.gse.models.serialize.type_exceptions import *
from fprime.gse.models.serialize.type_base import *
from fprime.common.models.serialize.type_exceptions import *
from fprime.common.models.serialize.type_base import *
from fprime.gse.models.serialize.bool_type import *
from fprime.gse.models.serialize.enum_type import *
from fprime.gse.models.serialize.f32_type import *
from fprime.gse.models.serialize.f64_type import *
from fprime.common.models.serialize.bool_type import *
from fprime.common.models.serialize.enum_type import *
from fprime.common.models.serialize.f32_type import *
from fprime.common.models.serialize.f64_type import *
from fprime.gse.models.serialize.u8_type import *
from fprime.gse.models.serialize.u16_type import *
from fprime.gse.models.serialize.u32_type import *
from fprime.gse.models.serialize.u64_type import *
from fprime.common.models.serialize.u8_type import *
from fprime.common.models.serialize.u16_type import *
from fprime.common.models.serialize.u32_type import *
from fprime.common.models.serialize.u64_type import *
from fprime.gse.models.serialize.i8_type import *
from fprime.gse.models.serialize.i16_type import *
from fprime.gse.models.serialize.i32_type import *
from fprime.gse.models.serialize.i64_type import *
from fprime.common.models.serialize.i8_type import *
from fprime.common.models.serialize.i16_type import *
from fprime.common.models.serialize.i32_type import *
from fprime.common.models.serialize.i64_type import *
from fprime.gse.models.serialize.string_type import *
from fprime.gse.models.serialize.serializable_type import *
from fprime.common.models.serialize.string_type import *
from fprime.common.models.serialize.serializable_type import *
from fprime.gse.models.common import command
from fprime.common.models.common import command

View File

@ -8,25 +8,25 @@ XML Source: ${source}
'''
# Import the types this way so they do not need prefixing for execution.
from fprime.gse.models.serialize.type_exceptions import *
from fprime.gse.models.serialize.type_base import *
from fprime.common.models.serialize.type_exceptions import *
from fprime.common.models.serialize.type_base import *
from fprime.gse.models.serialize.bool_type import *
from fprime.gse.models.serialize.enum_type import *
from fprime.gse.models.serialize.f32_type import *
from fprime.gse.models.serialize.f64_type import *
from fprime.common.models.serialize.bool_type import *
from fprime.common.models.serialize.enum_type import *
from fprime.common.models.serialize.f32_type import *
from fprime.common.models.serialize.f64_type import *
from fprime.gse.models.serialize.u8_type import *
from fprime.gse.models.serialize.u16_type import *
from fprime.gse.models.serialize.u32_type import *
from fprime.gse.models.serialize.u64_type import *
from fprime.common.models.serialize.u8_type import *
from fprime.common.models.serialize.u16_type import *
from fprime.common.models.serialize.u32_type import *
from fprime.common.models.serialize.u64_type import *
from fprime.gse.models.serialize.i8_type import *
from fprime.gse.models.serialize.i16_type import *
from fprime.gse.models.serialize.i32_type import *
from fprime.gse.models.serialize.i64_type import *
from fprime.common.models.serialize.i8_type import *
from fprime.common.models.serialize.i16_type import *
from fprime.common.models.serialize.i32_type import *
from fprime.common.models.serialize.i64_type import *
from fprime.gse.models.serialize.string_type import *
from fprime.gse.models.serialize.serializable_type import *
from fprime.common.models.serialize.string_type import *
from fprime.common.models.serialize.serializable_type import *
from fprime.gse.models.common import event
from fprime.common.models.common import event

View File

@ -1,23 +1,23 @@
# Import the types this way so they do not need prefixing for execution.
from fprime.gse.models.serialize.type_exceptions import *
from fprime.gse.models.serialize.type_base import *
from fprime.common.models.serialize.type_exceptions import *
from fprime.common.models.serialize.type_base import *
from fprime.gse.models.serialize.bool_type import *
from fprime.gse.models.serialize.enum_type import *
from fprime.gse.models.serialize.f32_type import *
from fprime.gse.models.serialize.f64_type import *
from fprime.common.models.serialize.bool_type import *
from fprime.common.models.serialize.enum_type import *
from fprime.common.models.serialize.f32_type import *
from fprime.common.models.serialize.f64_type import *
from fprime.gse.models.serialize.u8_type import *
from fprime.gse.models.serialize.u16_type import *
from fprime.gse.models.serialize.u32_type import *
from fprime.gse.models.serialize.u64_type import *
from fprime.common.models.serialize.u8_type import *
from fprime.common.models.serialize.u16_type import *
from fprime.common.models.serialize.u32_type import *
from fprime.common.models.serialize.u64_type import *
from fprime.gse.models.serialize.i8_type import *
from fprime.gse.models.serialize.i16_type import *
from fprime.gse.models.serialize.i32_type import *
from fprime.gse.models.serialize.i64_type import *
from fprime.common.models.serialize.i8_type import *
from fprime.common.models.serialize.i16_type import *
from fprime.common.models.serialize.i32_type import *
from fprime.common.models.serialize.i64_type import *
from fprime.gse.models.serialize.string_type import *
from fprime.gse.models.serialize.serializable_type import *
from fprime.common.models.serialize.string_type import *
from fprime.common.models.serialize.serializable_type import *

View File

@ -1,8 +0,0 @@
Cheetah
enum34
lxml
Markdown
multiprocess
pexpect
Pmw
wxPython

View File

@ -1,525 +0,0 @@
#!/usr/bin/env python
#===============================================================================
# NAME: tinyseqgen
#
# DESCRIPTION: A tiny sequence generator for F Prime. This sequence compiler takes a
# .seq file as input and produces a binary sequence file compatible with the
# F Prime sequence file loader and sequence file runner.
# AUTHOR: Kevin Dinkel
# EMAIL: dinkel@jpl.nasa.gov
# DATE CREATED: December 15, 2015
#
# Copyright 2015, California Institute of Technology.
# ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged.
#===============================================================================
import sys
import re
import os
import copy
from datetime import datetime, timedelta
from enum import Enum
from fprime.gds.models.serialize.time_type import *
from fprime.gds.models.serialize.bool_type import *
from fprime.gds.models.serialize.enum_type import *
from fprime.gds.models.serialize.f32_type import *
from fprime.gds.models.serialize.f64_type import *
from fprime.gds.models.serialize.u8_type import *
from fprime.gds.models.serialize.u16_type import *
from fprime.gds.models.serialize.u32_type import *
from fprime.gds.models.serialize.u64_type import *
from fprime.gds.models.serialize.i8_type import *
from fprime.gds.models.serialize.i16_type import *
from fprime.gds.models.serialize.i32_type import *
from fprime.gds.models.serialize.i64_type import *
from fprime.gds.models.serialize.string_type import *
from fprime.gds.models.serialize.serializable_type import *
import zlib
Descriptor = Enum(value='Descriptor', names='ABSOLUTE RELATIVE')
__author__ = "Kevin Dinkel"
__copyright__ = "Copyright 2015, California Institute of Technology."
__version__ = "1.0"
__email__ = "kevin.dinkel@jpl.nasa.gov"
class SeqBinaryWriter(object):
"""
Write out the Binary (ASTERIA) form of sequencer file.
"""
def __init__(self):
"""
Constructor
"""
self.__fd = None
def open(self, filename):
"""
Open the ASCII file
"""
self.__fd = open(filename, "wb")
def __binaryCmdRecord(self, cmd_obj):
"""
Return the binary command record the sequencer is expecting.
@todo: Currently the command descriptor is always zero for immediate commands.
@todo: Execution time tags needed in command objects and seq_panel.
"""
def __time_tag(cmd_obj):
'''
TODO: support a timebase in the cmd obj? This is mission specific, so it is tough to handle. For now
I am hardcoding this to 2 which is TB_NONE
'''
#return TimeType(timeBase=2, seconds=cmd_obj.getSeconds(), useconds=cmd_obj.getUseconds()).serialize()
# TKC - new command time format
return U32Type( cmd_obj[1].time.seconds ).serialize() + U32Type( cmd_obj[1].time.useconds ).serialize()
def __descriptor(cmd_obj):
# subtract 1 from the value because enum34 enums start at 1, and this can't be changed
return U8Type(cmd_obj[0].value-1).serialize()
def __command(cmd_obj):
command = U32Type( 0 ).serialize() # serialize combuffer type enum: FW_PACKET_COMMAND
command += U32Type( cmd_obj[1].template.get_op_code() ).serialize() # serialize opcode
# Command arguments
for arg in cmd_obj[1].get_args():
print(arg)
command += arg.serialize()
return command
def __length(command):
return U32Type( len(command) ).serialize()
def __print(byteBuffer):
print "Byte buffer size: %d" % len(byteBuffer)
for entry in range(0,len(byteBuffer)):
print "Byte %d: 0x%02X (%c)"%(entry,struct.unpack("B",byteBuffer[entry])[0],struct.unpack("B",byteBuffer[entry])[0])
# This is no longer in the sequence file format.
#def __checksum(data):
# csum = 0
# for entry in range(0,len(data)):
# byte = struct.unpack("B",data[entry])[0]
# csum += byte
# return U64Type(long(csum)).serialize()
# Form header:
descriptor = __descriptor(cmd_obj)
time = __time_tag(cmd_obj)
header = descriptor + time
# Command opcode:
command = __command(cmd_obj)
# Command length:
length = __length(command)
# Checksum:
# This is no longer in the sequence file format.
#checksum = __checksum(header + length + command)
# Debug printing (comment out when not debugging):
# print "descriptor:"
# __print(descriptor)
# print "time:"
# __print(time)
# print "length:"
# __print(length)
# print "command:"
# __print(command)
# print "total record:"
# __print(header + checksum + length + command)
# Construct the record:
return header + length + command
def write(self, seq_cmds_list):
"""
Write out each record as it appears in the listbox widget.
"""
num_records = len(seq_cmds_list)
sequence = ""
for cmd in seq_cmds_list:
sequence += self.__binaryCmdRecord(cmd)
size = len(sequence)
print("Sequence is %d bytes"%size)
header = ""
header += U32Type( size + 4 ).serialize() # Write out size of the sequence file in bytes here
header += U32Type( num_records ).serialize() # Write number of records
header += U16Type( 0xFFFF ).serialize() # Write time base FIXME: Set to don't care = 0xFFFF for now
header += U8Type( 0xFF ).serialize() # write time context
sequence = header + sequence # Write the list of command records here
# compute CRC. Ported from Utils/Hassh/libcrc/libcrc.h (update_crc_32)
crc = self.computeCrc(sequence)
print "CRC: %d (0x%04X)"%(crc,crc)
try:
sequence += U32Type( crc ).serialize()
except TypeMismatchException as typeErr:
print "Exception: %s" % typeErr.getMsg()
raise
# Write the list of command records here
self.__fd.write( sequence )
def close(self):
"""
Close the Binary file
"""
self.__fd.close()
def computeCrc(self, buff):
# See http://stackoverflow.com/questions/30092226/how-to-calculate-crc32-with-python-to-match-online-results
# RE: signed to unsigned CRC
return zlib.crc32(buff)% (1<<32)
class SeqAsciiWriter(object):
"""
Write out the ASCII record form of sequencer file.
"""
def __init__(self):
"""
Constructor
"""
self.__fd = None
def open(self, filename):
"""
Open the ASCII file
"""
self.__fd = open(filename, "w")
def __getCmdString(self, cmd_obj):
"""
For an command return it stringified.
"""
mnemonic = cmd_obj.getMnemonic()
opcode = cmd_obj.getOpCode()
args = cmd_obj.getArgs()
#
cmd = "%s (0x%x)" % (mnemonic,int(opcode))
for arg in args:
cmd += ", %s" % arg[2].val
return cmd
def write(self, seq_cmds_list):
"""
Write out each record as it appears in the listbox widget.
"""
for cmd in seq_cmds_list:
self.__fd.write(self.__getCmdString(cmd) + "\n")
def close(self):
"""
Close the ASCII file
"""
self.__fd.close()
def __error(string):
'''
Print an error message and exit with error code 1
@param string: the custom error string to print
'''
print string
sys.exit(1)
from fprime.gds.loaders import cmd_py_loader
from fprime.gds.data_types import cmd_data
# try:
# from fprime.gds.models.common.command import Descriptor
# TODO might want to reimplement but probably doesn't matter
from fprime.gds.controllers import exceptions as gseExceptions
# except:
# __error("The Gse source code was not found in your $PYTHONPATH variable. Please set PYTHONPATH to something like: $BUILD_ROOT/Gse/src:$BUILD_ROOT/Gse/generated/$DEPLOYMENT_NAME")
def __errorLine(lineNumber, string):
'''
Print an error message relating to a line number of the file input and exit with error code 1
@param lineNumber: the current line number being parsed
@param string: the custom error string to print
'''
__error("Error on line %d: %s" % (lineNumber + 1, string))
def __parse(seqfile):
'''
Generator that parses an input sequence file and returns a tuple
for each valid line of the sequence file.
@param seqfile: A sequence file name (usually a .seq extension)
@return A list of tuples:
(lineNumber, descriptor, seconds, useconds, mnemonic, arguments)
'''
def subQuoted(f, string):
'''
Run a substitution function on only substrings within a string that are surrounded
by single or double quotes
@param f: a string substitution acting on matchobjs
@param string: the string to perform the substitution on
@return the substituted string
'''
s = re.sub(r'"[^"]*"', f, string)
return re.sub(r"'[^']*'", f, s)
def removeTrailingComments(string):
'''
Remove any trailing comments (proceded by ';') in a string
@param string: the string to perform comment removal on
@return the string without trailing comments
'''
def replaceSemis(matchobj):
return matchobj.group(0).replace(';', ' ')
# ignore all semicolons in quotes:
s = subQuoted(replaceSemis, string)
s = subQuoted(replaceSemis, s)
# get index of first semicolon, and return everything before it:
if ';' in s:
index = s.index(';')
return string[:index]
# return original string if no semicolon found:
return string
def splitString(string):
'''
Split a string with ' ' or ',' as a delimiter. Ignore any delimiters
found within quoted substrings.
@param string: the string to perform the split on
@return a list representing the split string
'''
def replaceSpacesAndCommas(matchobj):
s = re.sub('\s', '_', matchobj.group(0))
s = re.sub('\,', '_', s)
return s
# ignore all spaces in quotes:
s = subQuoted(replaceSpacesAndCommas, string)
# replace all commas with spaces, since either can be a delimiter:
s = s.replace(',', ' ')
# get the split indices of the modified string:
indices = [(m.start(), m.end()) for m in re.finditer(r'\S+', s)]
toReturn = []
for start, end in indices:
toReturn.append(string[start:end])
return toReturn
def parseArgs(args):
'''
Turn .seq command argument list into their appropriate python types
@param args: a list of parsed arguments
@return a list of arguments as native python types
'''
def parseArg(arg):
# See if argument is a string, if so remove the quotes and return it:
if (arg[0] == '"' and arg[-1] == '"') or (arg[0] == "'" and arg[-1] == "'"):
return arg[1:-1]
# If the string contains a "." assume that it is a float:
elif "." in arg:
return float(arg)
else:
try:
# See if it translates to an integer:
return int(arg)
except ValueError:
try:
# See if it translates to a float:
return float(arg)
except ValueError:
# Otherwise it is an enum type:
return str(arg)
return map(parseArg, args)
def parseTime(lineNumber, time):
'''
Parse a time string and return the command descriptor, seconds, and useconds of the time string
@param lineNumber: the current line number where the time string was parsed
@param time: the time string to parse
@return a tuple (descriptor, seconds, useconds)
'''
def parseTimeStringOption(timeStr, timeFmts):
'''
Parse a time string by trying to use different time formats, until one succeeds
@param timeStr: the time string
@param timeFmts: the time format used to parse the string
@return the datetime object containing the parsed string
'''
def parseTimeString(timeFmt):
try:
return datetime.strptime(timeStr, timeFmt)
except:
return None
for fmt in timeFmts:
dt = parseTimeString(fmt)
if dt:
return dt
raise BaseException
def parseRelative(timeStr):
'''
Parse a relative time string
@param timeStr: the time string
@return the datetime object containing the parsed string
'''
options = ["%H:%M:%S.%f", "%H:%M:%S"]
return parseTimeStringOption(timeStr, options)
def parseAbsolute(timeStr):
'''
Parse an absolute time string
@param timeStr: the time string
@return the datetime object containing the parsed string
'''
options = ["%Y-%jT%H:%M:%S.%f","%Y-%jT%H:%M:%S"]
return parseTimeStringOption(timeStr, options)
descriptor = None
d = time[0]
t = time[1:]
if d == 'R':
descriptor = Descriptor.RELATIVE
dt = parseRelative(t)
delta = timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second, microseconds=dt.microsecond).total_seconds()
elif d == 'A':
descriptor = Descriptor.ABSOLUTE
dt = parseAbsolute(t)
# See if timezone was specified. If not, use UTC
if dt.tzinfo != None:
print "Using timezone %s" % dt.tzinfo.tzname()
epoch = datetime.fromtimestamp(0, dt.tzinfo)
else:
print "Using UTC timezone"
epoch = datetime.utcfromtimestamp(0)
delta = (dt - epoch).total_seconds()
else:
__error(lineNumber, "Invalid time descriptor '" + d + "' found. Descriptor should either be 'A' for absolute times or 'R' for relative times")
seconds = int(delta)
useconds = int((delta - seconds) * 1000000)
return descriptor, seconds, useconds
# Open the sequence file and parse each line:
with open(seqfile, "r") as inputFile:
for i, line in enumerate(inputFile):
line = line.strip()
# ignore blank lines and comments
if line and line[0] != ';':
line = removeTrailingComments(line)
line = splitString(line)
length = len(line)
if length < 2:
__errorLine(i, "Each line must contain a minimum of two fields, time and command mnemonic\n")
else:
try:
descriptor, seconds, useconds = parseTime(i, line[0])
except:
__errorLine(i, "Encountered syntax error parsing timestamp")
mnemonic = line[1]
args = []
if length > 2:
args = line[2:]
try:
args = parseArgs(args)
except:
__errorLine(i, "Encountered sytax error parsing arguments")
yield i, descriptor, seconds, useconds, mnemonic, args
def generateSequence(inputFile, outputFile=None):
'''
Write a binary sequence file from a text sequence file
@param inputFile: A text input sequence file name (usually a .seq extension)
@param outputFile: An output binary sequence file name (usually a .bin extension)
'''
# Check the user environment:
try:
generated_path = os.environ['GSE_GENERATED_PATH']
generated_command_path = generated_path + "/commands"
except:
__error("Environment variable 'GSE_GENERATED_PATH' not set. It should be set to something like '$BUILD_ROOT/Gse/generated/$DEPLOYMENT' and also added to $PYTHONPATH.")
command_loader = cmd_py_loader.CmdPyLoader()
try:
_, command_obj_dict = command_loader.construct_dicts(generated_command_path)
except Exception:
__error("Environment variable 'GSE_GENERATED_PATH' is set to '" + generated_path + "'. This is not a valid directory. Make sure this variable is set correctly, and the GSE python deployment autocode as been installed in this location.")
# Parse the input file:
command_list = []
for i, descriptor, seconds, useconds, mnemonic, args in __parse(inputFile):
# Make sure that command is in the command dictionary:
if mnemonic in command_obj_dict:
command_obj = cmd_data.CmdData(tuple([str(a) for a in args]), command_obj_dict[mnemonic], TimeType(seconds=seconds, useconds=useconds))
# Append this command to the command list:
command_list.append((descriptor, command_obj))
else:
__errorLine(i, "'" + mnemonic + "' does not match any command in the command dictionary.")
# Write to the output file:
writer = SeqBinaryWriter()
if not outputFile:
outputFile = os.path.splitext(inputFile)[0] + ".bin"
try:
writer.open(outputFile)
except:
__error("Encountered problem opening output file '" + outputFile + "'.")
writer.write(command_list)
writer.close()
if __name__ == "__main__":
'''
The main program if run from the commandline. Note that this file can also be used
as a module by calling the generateSequence() function
'''
if len(sys.argv) == 2 or len(sys.argv) == 3:
generateSequence(*sys.argv[1:])
else:
print "Usage: tinyseqgen sequence_file_in.seq [binary_sequence_file_out.bin]"
print
print "Welcome to tinyseqgen - the Tiny F Prime Command Sequence Generator."
print
print "Description: tinyseqgen takes a simple input sequence format (.seq),"
print "and outputs a binary command sequence loadable by the Svc/SequenceFileLoader."
print
print "Here, try out this example input sequence file (simple_sequence.seq):"
print
print ";--------------------------------------------------------------------"
print "; Simple sequence file "
print "; Note: that anything after a ';' is a comment"
print ";--------------------------------------------------------------------"
print
print "; Commands in a sequence can either be timed absolutely or relative "
print "; to the execution of the previous command. Here is an absolute NOOP"
print "; command. Make sure to use UTC times, since tinyseqgen will calculate"
print "; the seconds since the unix epoch from the given absolute time in UTC."
print "A2015-075T22:32:40.123 CMD_NO_OP"
print
print "; Here is a relative NOOP command, which will be run 1 second after"
print "; the execution of the previous command"
print "R00:00:01 CMD_NO_OP; Send a no op command"
print
print "; This command will run immediately after the previously executed command"
print "; has completed"
print "R00:00:00 CMD_NO_OP"
print
print "; Let's try out some commands with arguments"
print "R01:00:01.050 CMD_NO_OP_STRING \"Awesome string!\"; <- cool argument right?"
print "R03:51:01.000 CMD_TEST_CMD_1 17, 3.2, 2; <- this command has 3 arguments"
print "R00:05:00 ALOG_SET_EVENT_REPORT_FILTER INPUT_COMMAND, INPUT_DISABLED; <- this command uses enum arguments"
print
sys.exit(1)
sys.exit(0)

View File

@ -0,0 +1,84 @@
import Tkinter
import ttk
import logging
import Pmw
import sys
import os
import csv
import tkFileDialog
from optparse import OptionParser
from fprime.gse.utils import ConfigManager
from fprime.gse.controllers import channel_loader
from fprime.gse.models.tpe_models import SessionModel
from fprime.gse.controllers.tpe_controllers import SessionController
from fprime.gse.controllers.exceptions import GseControllerUndefinedDirectoryException
# Setup logging
Logger = logging.getLogger(__name__)
sh = logging.StreamHandler()
#sh.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
Logger.addHandler(sh)
Logger.setLevel(logging.DEBUG)
def main(opts):
root = Tkinter.Tk()
root.minsize(500, 600)
root.title("F Prime Telemetry Packet Editor")
# Try to load channels.
ch_path = os.path.join(opts.gen_path, "channels")
ch_loader = channel_loader.ChannelLoader.getInstance()
# Exit if they are not found.
try:
ch_loader.create(ch_path)
except GseControllerUndefinedDirectoryException, e:
alert_dialog(root)
return
session_model = SessionModel(ch_loader)
session_controller = SessionController(opts, root, session_model)
session_controller.create_session()
root.mainloop()
def alert_dialog(parent):
dialog = Pmw.MessageDialog(parent,
title = 'Error',
buttons=('Exit',),
iconpos = 'w',
icon_bitmap = 'error',
message_text = 'Cannot find channel dictionaries. Specify generated dictionary path with -d.')
dialog.iconname('Generated Dictionary Error')
dialog.activate()
if __name__ == '__main__':
argv = sys.argv[1:]
program_version_string = "1.0"
program_longdesc = ""
program_license = ""
config_manager = ConfigManager.ConfigManager.getInstance()
generated_path = config_manager.get("filepaths", "generated_path")
parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
parser.add_option("-d", "--dictionary", dest="gen_path", action="store", type="string", \
help="Set base path to generated command/telemetry definition files [default: %default]", \
default=generated_path)
(opts, args) = parser.parse_args(argv)
# Add to path so we can import channels
sys.path.append(opts.gen_path)
main(opts)

View File

@ -0,0 +1,645 @@
#!/usr/bin/env python
import matplotlib
matplotlib.use('TkAgg')
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from Tkinter import *
import sys
import threading
import Queue
import os
import math
import Pmw
import struct
import math
import time
from fprime.gse.controllers import client_sock
#import ModeMgrSm
class Plotter:
"""
Class to accept telemetry from multi-partiiions and sends commands.
It also launches thread to generate fake simulation data.
"""
def __init__(self, master, width=500, height=350):
"""
Constructor
"""
self.root = master
# Title
self.status = Label(master, text="Multi-Partition Telemetry & Commander", justify=LEFT)
self.status.pack(side=TOP)
# Entry fields to support commands
self.control3 = Frame(master)
self.control3.pack(side=BOTTOM, fill=X, padx=2)
# Buttons to launch demos
self.control2 = Frame(master)
self.control2.pack(side=BOTTOM, fill=X, padx=2)
# Buttons to launch demos
self.control = Frame(master)
self.control.pack(side=BOTTOM, fill=X, padx=2)
# Build temp plot here for testing
self.fig = Figure(figsize=(6,3), dpi=100)
self.axis = self.fig.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
t=[]
s=[]
# Initialize plots
self.axis.plot(t,s)
# Label title, axis and turn on grid
self.label_plot()
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(self.fig, master=master)
canvas.show()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
#
toolbar = NavigationToolbar2TkAgg( canvas, master )
toolbar.update()
canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
#
self.display = Pmw.ScrolledText(self.root, hscrollmode='dynamic',
vscrollmode='dynamic', hull_relief='sunken',
hull_background='gray40', hull_borderwidth=10,
text_background='white', text_width=16,
text_foreground='black', text_height=10,
text_padx=10, text_pady=10, text_relief='groove',
text_font=('arial', 12, 'bold'))
self.display.pack(side=TOP, expand=YES, fill=BOTH)
self.display.tag_config('ans', foreground='red')
self.display.tag_config('blue', foreground='blue')
self.display.tag_config('red', foreground='red')
self.display.tag_config('green', foreground='green')
self.display.tag_config('black', foreground='black')
# Quit
self.quit_bt = Button(self.control, text='Quit', activebackground="pink", command=self.quit)
self.quit_bt.pack(side=LEFT, fill=X, expand=True)
# Connect
self.connect_bt = Button(self.control, text='Connect', activebackground="pink", command=self.connect)
self.connect_bt.pack(side=LEFT, fill=X, expand=True)
# Clear
self.clear_bt = Button(self.control, text='Clear', activebackground="pink", command=self.clear)
self.clear_bt.pack(side=LEFT, fill=X, expand=True)
# Play
self.play_bt = Button(self.control, text='List', activebackground="pink", command=self.list)
self.play_bt.pack(side=LEFT, fill=X, expand=True)
# Pause
self.pause_bt = Button(self.control, text='Play', activebackground="pink", command=self.play)
self.pause_bt.pack(side=LEFT, fill=X, expand=True)
# Stop
self.stop_bt = Button(self.control, text='Stop', activebackground="pink", command=self.stop)
self.stop_bt.pack(side=LEFT, fill=X, expand=True)
# opcode 1
self.op1_bt = Button(self.control2, text='Mode Change', activebackground="pink", command=self.op1)
self.op1_bt.pack(side=LEFT, fill=X, expand=True)
# opcode 2
self.op2_bt = Button(self.control2, text='Set Param', activebackground="pink", command=self.op2)
self.op2_bt.pack(side=LEFT, fill=X, expand=True)
# opcode 3
self.op3_bt = Button(self.control2, text='Get Param', activebackground="pink", command=self.op3)
self.op3_bt.pack(side=LEFT, fill=X, expand=True)
# opcode 4
self.op4_bt = Button(self.control2, text='Test Cent. (x,y)', activebackground="pink", command=self.op4)
self.op4_bt.pack(side=LEFT, fill=X, expand=True)
# opcode 5
self.op5_bt = Button(self.control2, text='Test ARS Data', activebackground="pink", command=self.op5)
self.op5_bt.pack(side=LEFT, fill=X, expand=True)
#
# Entry fields to support command.
#
self.mode_signal = 1
self.signals = ["OnCmd", "OffCmd", "ARS_On", "ARS_Off", "Centroid_On", "Centroid_Off",
"Show_SM_GUI", "Hide_SM_GUI"]
self.mode_entry = Pmw.ComboBox(self.control3,
scrolledlist_items=self.signals,
selectioncommand = self.changeMode)
self.mode_entry.pack(side=LEFT, fill=X, expand=False)
self.mode_entry.selectitem(0, setentry = 1)
self.mode_entry.component("entryfield").configure(validate=self.validateMode)
#
self.set_param = Pmw.EntryField(self.control3, value=1.0,
validate='real')
self.set_param.pack(side=LEFT, fill=X, expand=False)
#
self.get_param = Pmw.EntryField(self.control3, value="Params",
validate='alphanumeric')
self.get_param.pack(side=LEFT, fill=X, expand=False)
#
self.test_cent = Pmw.EntryField(self.control3, value='0 0',
validate=self.cent_coord_validate)
self.test_cent.pack(side=LEFT, fill=X, expand=False)
self.cent_coord_validate_ok = True
#
self.test_ars = Pmw.EntryField(self.control3, value='0.0 0.0 0.0',
validate=self.ars_validate)
self.test_ars.pack(side=LEFT, fill=X, expand=False)
self.ars_validate_ok = True
#
# Socket when connection established
#
self.sock = None
# Store thread here
self.thread = threading.Thread()
self.thread2 = threading.Thread()
# Instance a lock and make all socket read/write atomic
self.lock = threading.Lock()
# Create Queue for telemetry here
self.queue = Queue.Queue()
# Create Queue for simulation data here
self.queue2 = Queue.Queue()
# Define plot format for each instance here
# Note that instance id is index to list
# Note: Adding a "-" results in lines in replot only.
self.plot_fmt = []
self.plot_fmt.append("ro")
self.plot_fmt.append("g^")
self.plot_fmt.append("c<")
self.plot_fmt.append("m>")
#
self.i = 0
#
width = 600
height = 600
x = 500
y = 500
# self.mode_mgr_sm_win = ModeMgrSm.ModeMgrSm("ModeMgrSm", big_name="Mode Manager State Machine", size=16)
# self.mode_mgr_sm_win.win.geometry("%dx%d+%d+%d" % (width, height, x, y))
# self.mode_mgr_sm_win.win.withdraw()
def cent_coord_validate(self, text):
"""
Check that entry is (x y) where x and y are integer.
"""
self.cent_coord_validate_ok = False
if len(text.split(" ")) != 2:
return Pmw.PARTIAL
x,y = text.split(" ")
if not x.isdigit():
return Pmw.PARTIAL
if not y.isdigit():
return Pmw.PARTIAL
self.cent_coord_validate_ok = True
return Pmw.OK
def ars_validate(self, text):
"""
Check that entry is (x y z) where x, y, z are float.
"""
self.ars_validate_ok = False
if len(text.split(" ")) != 3:
return Pmw.PARTIAL
x,y,z = text.split(" ")
xp = x.partition(".")
if not (xp[0].isdigit() and xp[1]=='.' and xp[2].isdigit()):
return Pmw.PARTIAL
yp = y.partition(".")
if not (yp[0].isdigit() and yp[1]=='.' and yp[2].isdigit()):
return Pmw.PARTIAL
zp = z.partition(".")
if not (zp[0].isdigit() and zp[1]=='.' and zp[2].isdigit()):
return Pmw.PARTIAL
self.ars_validate_ok = True
return Pmw.OK
def set_demo_lim(self):
"""
Set axis limits for long trajectory demo.
"""
self.axis.set_xlim(0.0, 50.0)
#self.axis.set_ylim(-1.25, 1.25)
self.axis.set_ylim(-50.0, 50.0)
def set_auto_lim(self):
"""
Set autoscale of axis
"""
self.axis.relim()
self.axis.autoscale_view(True,True,True)
def label_plot(self):
"""
Refresh plot labels and settings
"""
self.axis.grid()
self.axis.set_title("Notional Tip/Tilt Position Update")
self.axis.set_ylabel("Tip/Tilt (radians)")
self.axis.set_xlabel("N (counts)")
# Set default xy axis
self.set_demo_lim()
# Button row 1 functionality here...
def list(self):
self.root.update_idletasks()
if self.sock != None:
self.lock.acquire()
self.sock.send("List\n")
self.lock.release()
else:
self.status.config(text="SOCKET NOT CONNECTED TO SERVER...", fg="red")
def play(self):
self.root.update_idletasks()
if self.sock != None:
self.queue2.put("PLAY")
self.display.insert(END, "Sent PLAY request to sim thread...\n", "green")
else:
self.status.config(text="SOCKET NOT CONNECTED TO SERVER...", fg="red")
def stop(self):
self.root.update_idletasks()
if self.sock != None:
self.queue2.put("STOP")
self.display.insert(END, "Sent STOP request to sim thread...\n", "green")
else:
self.status.config(text="SOCKET NOT CONNECTED TO SERVER...", fg="red")
# Button row 2 functionality here...
def app_cmd(self, msg):
"""
Package command for server to send to APP
"""
if self.sock != None:
cmd = "A5A5 " + "APP " + msg
self.lock.acquire()
self.sock.send(cmd)
self.lock.release()
else:
self.status.config(text="SOCKET NOT CONNECTED TO SERVER...", fg="red")
def app_cmd_fmt(self, op,s1,i1,i2,f1,f2):
"""
Packet format for basic command
"""
n = 0
l = 80
fmt = "Message sent: (%d,%s,%d,%d,%d,%f,%f,%d)\n"
msg = struct.pack(">I80s3i",op,s1,l,i1,i2) + struct.pack("2f",f1,f2) + struct.pack(">i",n)
print fmt % (op,s1,l,i1,i2,f1,f2,n)
self.display.insert(END, fmt % (op,s1,l,i1,i2,f1,f2,n), "black")
self.display.see(END)
return msg
def op1(self):
"""
Execute op 1 command
"""
val = int(self.mode_signal)
msg = self.app_cmd_fmt(1, "", val, 0, 0.0, 0.0)
self.app_cmd(msg)
def changeMode(self, text):
"""
Set the mode manager mode, or hide/show mode mgr display
"""
item = self.mode_entry.getvalue()[0]
if item == "Show_SM_GUI":
self.mode_signal = 1
self.mode_mgr_sm_win.win.deiconify()
self.mode_mgr_sm_win.win.lift(self.root)
elif item == "Hide_SM_GUI":
self.mode_signal = 1
self.mode_mgr_sm_win.win.withdraw()
elif item.isdigit():
self.mode_signal = int(item)
else:
self.mode_signal = self.signals.index(item) + 1
# print self.mode_signal
def validateMode(self, text):
"""
Validate mode is in the list or a number of 1 to 6 here.
"""
if text in self.signals:
return Pmw.OK
if text.isdigit():
if 0 < int(text) < 7:
return Pmw.OK
return Pmw.PARTIAL
def op2(self):
val = float(self.set_param.getvalue())
msg = self.app_cmd_fmt(2, "", 0, 0, val, 0.0)
self.app_cmd(msg)
def op3(self):
val = self.get_param.getvalue()
msg = self.app_cmd_fmt(3, val, 0, 0, 0.0, 0.0)
self.app_cmd(msg)
def op4(self):
"""
Send x, y and increment each time...
"""
if self.cent_coord_validate_ok:
val = self.test_cent.getvalue().split(" ")
n = 1
x = int(val[0])
y = int(val[1])
msg = struct.pack(">3i",x,y,n)
#
# Make msg 108 bytes like command
buf = 96*"A5"
msg = struct.pack(">96s",buf) + msg
self.app_cmd(msg)
self.display.insert(END, "opcode=%d, Coord=(%d,%d)\n" % (n,x,y),"black")
self.display.see(END)
def op5(self):
"""
Send x, y, z and increment each fractionally...
"""
if self.ars_validate_ok:
c = self.test_ars.getvalue().split(" ")
n = 2
f1 = float(c[0])
f2 = float(c[1])
f3 = float(c[2])
msg = struct.pack("3f",f1,f2,f3) + struct.pack(">i",n)
#
# Make msg 108 bytes like command
buf = 92*"A5"
msg = struct.pack(">92s",buf) + msg
self.app_cmd(msg)
self.display.insert(END, "opcode=%d, Angles=(%f,%f,%f)\n" % (n,f1,f2,f3),"black")
self.display.see(END)
def quit(self):
"""
Quit the plotter
"""
self.clear()
root.quit()
root.destroy()
def receive_telemetry(self, sock):
"""
Receive telemetry by first reading 4 byte size,
then reading size bytes of serial telemetry
and returning it as a message.
"""
msg = sock.recv(4)
size = int(struct.unpack("i",msg)[0])
data = sock.recv(size)
return data
def enqueue_output(self, sock, queue):
"""
Queue up socket telemetry for TK processing
"""
while 1:
try:
#x = sock.receive()
x = self.receive_telemetry(sock)
queue.put(x)
except RuntimeError:
queue.put("terminate")
print "Socket connection terminated"
break
return
def enqueue_sim_output(self, sock, queue):
"""
Queue up socket sim ARS data for C++ app commanding
"""
angle = 0.0
while 1:
try:
msg = queue.get()
if msg == "PLAY":
while 1:
# Update rate is 2 hz.
time.sleep(0.5)
# Compute x, y, z sin phased by 45 degree each
P = 45.0 * (math.pi/180.0)
# Phase
G = 1.0
# Angle sin values
x = G * math.sin(angle)
y = G * math.sin(angle + P)
z = G * math.sin(angle + 2*P)
# Angle increment value
angle += 10.0 * (math.pi/180.0)
#print time.time(), x, y, z
n = 2
msg = struct.pack("3f",x,y,z) + struct.pack(">i",n)
#
# Make msg 108 bytes like command
buf = 92*"A5"
msg = struct.pack(">92s",buf) + msg
#
self.app_cmd(msg)
if not queue.empty():
msg = queue.get()
print msg
if msg == "STOP":
angle = 0.0
break
elif msg == "STOP":
pass
elif msg == "RESET":
pass
else:
pass
except RuntimeError:
queue.put("terminate")
print "Socket connection terminated"
break
def connect(self):
"""
Connect to TRN filter state telemetry socket
and start listener thread.
"""
if self.thread.isAlive() == True:
print "LISTENER THREAD IS ALIVE!"
return
# connect to server TRN
try:
port = 50007
server = "127.0.0.1"
str = "Connected to server (host addr %s, port %d)" % (server, port)
self.sock=client_sock.ClientSocket(server,port)
#
# Register the GUI with the server
self.lock.acquire()
self.sock.send("Register GUI\n")
self.lock.release()
except IOError:
str = "EXCEPTION: Could not connect to socket at host addr %s, port %s" % (server, port)
# update status
self.status.config(text=str, fg="red")
self.connect_bt.config(text="Disconnected", fg="black")
self.sock = None
return
if self.thread.daemon == False:
# create background listener thread
self.thread = threading.Thread(target=self.enqueue_output, args=(self.sock, self.queue))
# thread dies with the program
self.thread.daemon = True
# state listener thread here
self.thread.start()
if self.thread2.daemon == False:
# create background sim data generator thread
self.thread2 = threading.Thread(target=self.enqueue_sim_output, args=(self.sock, self.queue2))
# thread dies with the program
self.thread2.daemon = True
# start simulation thread here
self.thread2.start()
# update status
self.status.config(text=str, fg="red")
self.connect_bt.config(text="Connected", fg="red")
def clear(self):
"""
Clear all plots
"""
#if self.thread.isAlive() == True:
# self.status.config(text="LISTENER THREAD IS ALIVE!",fg="red")
# return
self.i = 0
self.axis.cla()
self.label_plot()
self.fig.canvas.draw()
self.status.config(text="Cleared plot areas.",fg="black")
self.fig.canvas.draw()
self.display.clear()
def updatePlots(self, n, x, y):
"""
Update plot with new point
"""
fmt = self.plot_fmt[0]
fmt2 = self.plot_fmt[1]
if n % 50.0 == 0:
self.axis.set_xlim(n, n+50.0)
self.axis.plot(n,x,fmt)
self.axis.plot(n,y,fmt2)
#
# Update figure here
self.fig.canvas.draw()
def decode_telm(self, bmsg):
"""
Decode APP telemetry here and return a tuple.
"""
if bmsg[:4] == "List":
bmsg = bmsg.split(" ")
print "---Server connected to %s" % bmsg[1]
self.display.insert(END, "---Server connected to %s\n" % bmsg[1], "blue")
return []
l = len(bmsg)
msg = struct.unpack(">" + "%d" % l + "s",bmsg)
#print msg
#tid = struct.unpack(">i",msg[0][-5:-1])[0]
tid = struct.unpack(">i",msg[0][-4:])[0]
if tid == 1:
args = struct.unpack("3f",msg[0][:-4])
print "--- (raw tlm ARSDATA) %f, %f, %f\n" % args
self.display.insert(END, "--- (raw tlm ARSDATA) %f, %f, %f\n" % args, "ans")
l = [tid, args[0],args[1],args[2]]
elif tid == 2:
args = struct.unpack("2f",msg[0][:-4])
print "--- (raw tlm FSMDATA) %f, %f\n" % args
self.display.insert(END, "--- (raw tlm FSMDATA) %f, %f\n" % args, "ans")
l = [tid, args[0],args[1]]
elif tid == 3:
args = struct.unpack("f",msg[0][:-4])
print "--- (raw tlm PARAMDATA) %f\n" % args[0]
self.display.insert(END, "--- (raw tlm PARAMDATA) %f\n" % args, "ans")
l = [tid, args[0]]
elif tid == 4:
m = msg[0][0:80]
args = struct.unpack("80s",m)
print "--- (State Data) %s\n" % args
self.display.insert(END, "--- (State Data) %s\n\n" % args, "ans")
self.display.insert(END, "\n")
l = [tid, args]
else:
print "Unrecognized telemetry id = %d\n" % tid
self.display.insert(END, "ERROR: Unrecognized telemetry id = %d\n" % tid, "ans")
l = []
self.display.see(END)
#print "Id is %d, msg is %s, args is %s" % (tid,msg,args)
return l
def update_task(self):
"""
Update telemetry and plots from socket here...
"""
time_period = 20
time_period_no_output = 200
# read line without blocking
try:
msg = self.queue.get_nowait()
#print msg
msg = self.decode_telm(msg)
if len(msg) > 0:
if msg[0] == 2:
n = self.i
x = msg[1]
y = msg[2]
self.updatePlots(n, x, y)
self.i += 1
if msg[0] == 4:
state = msg[1][0].split(":")
e = state[1].split(" ")[-1].strip("\x00")
s1 = state[0]
s2 = state[1].strip(" "+e).replace(" ","")
s2 = s2.strip("\x00")
s2 = s2.strip("ENTRY")
s2 = s2.strip("EXIT")
state = s2 + ":" + s1
#
if e == "EXIT":
self.mode_mgr_sm_win.ExitState(state)
if e == "ENTRY":
self.mode_mgr_sm_win.EnterState(state)
#
except Queue.Empty:
#print('no output yet')
self.root.after(time_period_no_output, self.update_task)
return
# ... do something with line
#
self.mode_mgr_sm_win.win.update_idletasks()
self.root.update_idletasks()
self.root.after(time_period, self.update_task)
return
if __name__ == '__main__':
root = Tk()
root.option_add('*Font', 'Verdana 10')
root.title('Multi-Partition Demo Commander and Telmetry Monitor')
p = Plotter(root)
root.after(200, p.update_task)
root.mainloop()

View File

@ -0,0 +1,60 @@
#!/bin/env python
import os
import sys
import time
from fprime.gse.utils.gse_api import GseApi
from optparse import OptionParser
__version__ = 0.1
__date__ = '2015-08-01'
__updated__ = '2015-08-01'
def main(argv=None):
if argv is None:
argv =sys.argv[1:]
try:
program_name = os.path.basename(sys.argv[0])
program_version = "v0.1"
program_build_date = "%s" % __updated__
program_longdesc = '''''' # optional - give further explanation about what the program does
program_license = "Copyright 2015 user_name (California Institute of Technology) \
ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged."
program_version_string = '%%prog %s (%s)' % (program_version, program_build_date)
if argv is None:
argv = sys.argv[1:]
parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
parser.add_option("-d", "--dictionary", dest="generated_path", action="store", type="string", \
help="Set base path to generated command/telemetry definition files")
parser.add_option("-a", "--addr", dest="addr", action="store", type="string", help="set threaded tcp socket server address [default: %default]", \
default="127.0.0.1")
parser.add_option("-c", "--connect", action="store_true", dest="connect", help="Launches the Threaded TCP Socket Server on startup and connect to it [default: %default]", \
default=False)
parser.add_option("-p", "--port", dest="port", action="store", type="int", help="Set threaded tcp socket server port [default: %default]", \
default=50000)
#TODO: add arg to provide list of ids to monitor
(opts, args) = parser.parse_args(argv)
except Exception, e:
indent = len(program_name) * " "
sys.stderr.write(program_name + ": " + repr(e) + "\n")
sys.stderr.write(indent + " for help use --help\n")
return 2
api = GseApi(generated_path=opts.generated_path, port=opts.port)
cmd_list = api.list()
print "List of commands found:", cmd_list
time.sleep(1)
api.send("CMD_NO_OP")
time.sleep(1)
api.send("CMD_NO_OP_STRING", args=['Foo'])
time.sleep(1)
api.send_wait_evr("CMD_TEST_CMD_1", 'OpCodeCompleted',[1,2.0,3])
time.sleep(1)
api.send_wait_tlm("CMD_NO_OP", 'OpCodeCompleted', timeout = 10, args=None)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,59 @@
#!/bin/env python
import os
import sys
#from gse_api import GseApi
from fprime.gse.utils.gse_api import GseApi
from optparse import OptionParser
__version__ = 0.1
__date__ = '2015-08-01'
__updated__ = '2015-08-01'
def main(argv=None):
if argv is None:
argv =sys.argv[1:]
try:
program_name = os.path.basename(sys.argv[0])
program_version = "v0.1"
program_build_date = "%s" % __updated__
program_longdesc = '''''' # optional - give further explanation about what the program does
program_license = "Copyright 2015 user_name (California Institute of Technology) \
ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged."
program_version_string = '%%prog %s (%s)' % (program_version, program_build_date)
if argv is None:
argv = sys.argv[1:]
parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
parser.add_option("-d", "--dictionary", dest="generated_path", action="store", type="string", \
help="Set base path to generated command/telemetry definition files")
parser.add_option("-a", "--addr", dest="addr", action="store", type="string", help="set threaded tcp socket server address [default: %default]", \
default="127.0.0.1")
parser.add_option("-c", "--connect", action="store_true", dest="connect", help="Launches the Threaded TCP Socket Server on startup and connect to it [default: %default]", \
default=False)
parser.add_option("-p", "--port", dest="port", action="store", type="int", help="Set threaded tcp socket server port [default: %default]", \
default=50000)
parser.add_option("-m", "--monitor", dest="monitor", action="store", type="string", help="Set type of telemetry to monitior [default: %default]", \
default='ch')
#TODO: add arg to provide list of ids to monitor
(opts, args) = parser.parse_args(argv)
api = GseApi(generated_path=opts.generated_path, port=opts.port)
if opts.monitor == 'evr':
print 'Listening for event telemetry'
api.monitor_evr()
else:
print 'Listening for channelized telemetry'
api.monitor_tlm()
except Exception, e:
indent = len(program_name) * " "
sys.stderr.write(program_name + ": " + repr(e) + "\n")
sys.stderr.write(indent + " for help use --help\n")
return 2
if __name__ == "__main__":
main()

View File

@ -1,4 +1,4 @@
#!/bin/csh
#!/bin/sh
# *******************************************************************************
# * Copyright 2013, by the California Institute of Technology.
# * ALL RIGHTS RESERVED. United States Government Sponsorship
@ -13,23 +13,13 @@
# * information to foreign countries or providing access to foreign
# * persons.
# *
if !($?BUILD_ROOT) then
set curdir = "${PWD}"
setenv BUILD_ROOT `dirname $0`/../..
cd $BUILD_ROOT
setenv BUILD_ROOT ${PWD}
cd ${curdir}
endif
DIRNAME="`dirname $0`"
# Set BUILD_ROOT if unset or "" set the BUILD_ROOT to be the above dir
if [ -z ${BUILD_ROOT} ]
then
export BUILD_ROOT="`cd ${DIRNAME}/../../..; pwd`"
fi
echo "BUILD_ROOT is: ${BUILD_ROOT}"
# Borrow some variables from build
setenv PYTHON_BASE `make -s -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk print_python_base`
echo "PYTHON_BASE: ${PYTHON_BASE}"
setenv LD_LIBRARY_PATH ${PYTHON_BASE}/lib
setenv PYTHONPATH ${BUILD_ROOT}/Gds/src
setenv GSE_GENERATED_PATH ${BUILD_ROOT}/Gse/generated/Ref
${PYTHON_BASE}/bin/python ${BUILD_ROOT}/Gds/bin/tinyseqgen.py $*
export PYTHONPATH="${BUILD_ROOT}/Gds"
python "${BUILD_ROOT}/Gds/tkGui/bin/seqgen.py" "$@"

31
Gds/tkGui/bin/run_tlmeditor.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
# *******************************************************************************
# * Copyright 2013, by the California Institute of Technology.
# * ALL RIGHTS RESERVED. United States Government Sponsorship
# * acknowledged. Any commercial use must be negotiated with the Office
# * of Technology Transfer at the California Institute of Technology.
# *
# * This software may be subject to U.S. export control laws and
# * regulations. By accepting this document, the user agrees to comply
# * with all applicable U.S. export laws and regulations. User has the
# * responsibility to obtain export licenses,
# * or other export authority as may be required before exporting such
# * information to foreign countries or providing access to foreign
# * persons.
# *
DIRNAME="`dirname $0`"
# Set BUILD_ROOT if unset or "" set the BUILD_ROOT to be the above dir
if [ -z ${BUILD_ROOT} ]
then
export BUILD_ROOT="`cd ${DIRNAME}/../..; pwd`"
fi
echo "BUILD_ROOT is: ${BUILD_ROOT}"
# Get binary output path
export NATIVE_BUILD="`make -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk print_native_build`"
echo "NATIVE_BUILD: ${NATIVE_BUILD}"
export OUTPUT_DIR="`make -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk BUILD=$NATIVE_BUILD print_output_dir`"
echo "OUTPUT_DIR: ${OUTPUT_DIR}"
export PYTHONPATH="${BUILD_ROOT}/Gse/src"
python "${BUILD_ROOT}/Gse/bin/TLMPacketEditor.py" "$@"

320
Gds/tkGui/bin/seqgen.py Executable file
View File

@ -0,0 +1,320 @@
#!/usr/bin/env python
#===============================================================================
# NAME: tinyseqgen
#
# DESCRIPTION: A tiny sequence generator for F Prime. This sequence compiler takes a
# .seq file as input and produces a binary sequence file compatible with the
# F Prime sequence file loader and sequence file runner.
# AUTHOR: Kevin Dinkel
# EMAIL: dinkel@jpl.nasa.gov
# DATE CREATED: December 15, 2015
#
# Copyright 2015, California Institute of Technology.
# ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged.
#===============================================================================
import sys
import re
import os
import copy
from datetime import datetime, timedelta
from optparse import OptionParser
from fprime.common.models.serialize.type_exceptions import *
__author__ = "Kevin Dinkel"
__copyright__ = "Copyright 2015, California Institute of Technology."
__version__ = "1.0"
__email__ = "kevin.dinkel@jpl.nasa.gov"
def __error(string):
'''
Print an error message and exit with error code 1
@param string: the custom error string to print
'''
print string
sys.exit(1)
# try:
from fprime.common.models.common.command import Descriptor
from tkGui.views.seq_panel import SeqBinaryWriter
from tkGui.gse.controllers import command_loader
from tkGui.gse.controllers import exceptions as gseExceptions
# except:
# __error("The Gse source code was not found in your $PYTHONPATH variable. Please set PYTHONPATH to something like: $BUILD_ROOT/Gse/src:$BUILD_ROOT/Gse/generated/$DEPLOYMENT_NAME")
def __errorLine(lineNumber, string):
'''
Print an error message relating to a line number of the file input and exit with error code 1
@param lineNumber: the current line number being parsed
@param string: the custom error string to print
'''
__error("Error on line %d: %s" % (lineNumber + 1, string))
def __parse(seqfile):
'''
Generator that parses an input sequence file and returns a tuple
for each valid line of the sequence file.
@param seqfile: A sequence file name (usually a .seq extension)
@return A list of tuples:
(lineNumber, descriptor, seconds, useconds, mnemonic, arguments)
'''
def subQuoted(f, string):
'''
Run a substitution function on only substrings within a string that are surrounded
by single or double quotes
@param f: a string substitution acting on matchobjs
@param string: the string to perform the substitution on
@return the substituted string
'''
s = re.sub(r'"[^"]*"', f, string)
return re.sub(r"'[^']*'", f, s)
def removeTrailingComments(string):
'''
Remove any trailing comments (proceded by ';') in a string
@param string: the string to perform comment removal on
@return the string without trailing comments
'''
def replaceSemis(matchobj):
return matchobj.group(0).replace(';', ' ')
# ignore all semicolons in quotes:
s = subQuoted(replaceSemis, string)
s = subQuoted(replaceSemis, s)
# get index of first semicolon, and return everything before it:
if ';' in s:
index = s.index(';')
return string[:index]
# return original string if no semicolon found:
return string
def splitString(string):
'''
Split a string with ' ' or ',' as a delimiter. Ignore any delimiters
found within quoted substrings.
@param string: the string to perform the split on
@return a list representing the split string
'''
def replaceSpacesAndCommas(matchobj):
s = re.sub('\s', '_', matchobj.group(0))
s = re.sub('\,', '_', s)
return s
# ignore all spaces in quotes:
s = subQuoted(replaceSpacesAndCommas, string)
# replace all commas with spaces, since either can be a delimiter:
s = s.replace(',', ' ')
# get the split indices of the modified string:
indices = [(m.start(), m.end()) for m in re.finditer(r'\S+', s)]
toReturn = []
for start, end in indices:
toReturn.append(string[start:end])
return toReturn
def parseArgs(args):
'''
Turn .seq command argument list into their appropriate python types
@param args: a list of parsed arguments
@return a list of arguments as native python types
'''
def parseArg(arg):
# See if argument is a string, if so remove the quotes and return it:
if (arg[0] == '"' and arg[-1] == '"') or (arg[0] == "'" and arg[-1] == "'"):
return arg[1:-1]
# If the string contains a "." assume that it is a float:
elif "." in arg:
return float(arg)
elif arg == 'True' or arg == 'true' or arg == 'TRUE':
return True
elif arg == 'False' or arg == 'false' or arg == 'FALSE':
return False
else:
try:
# See if it translates to an integer:
return int(arg,0)
except ValueError:
try:
# See if it translates to a float:
return float(arg)
except ValueError:
# Otherwise it is an enum type:
return str(arg)
return map(parseArg, args)
def parseTime(lineNumber, time):
'''
Parse a time string and return the command descriptor, seconds, and useconds of the time string
@param lineNumber: the current line number where the time string was parsed
@param time: the time string to parse
@return a tuple (descriptor, seconds, useconds)
'''
def parseTimeStringOption(timeStr, timeFmts):
'''
Parse a time string by trying to use different time formats, until one succeeds
@param timeStr: the time string
@param timeFmts: the time format used to parse the string
@return the datetime object containing the parsed string
'''
def parseTimeString(timeFmt):
try:
return datetime.strptime(timeStr, timeFmt)
except:
return None
for fmt in timeFmts:
dt = parseTimeString(fmt)
if dt:
return dt
raise BaseException
def parseRelative(timeStr):
'''
Parse a relative time string
@param timeStr: the time string
@return the datetime object containing the parsed string
'''
options = ["%H:%M:%S.%f", "%H:%M:%S"]
return parseTimeStringOption(timeStr, options)
def parseAbsolute(timeStr):
'''
Parse an absolute time string
@param timeStr: the time string
@return the datetime object containing the parsed string
'''
options = ["%Y-%jT%H:%M:%S.%f","%Y-%jT%H:%M:%S"]
return parseTimeStringOption(timeStr, options)
descriptor = None
d = time[0]
t = time[1:]
if d == 'R':
descriptor = Descriptor.RELATIVE
dt = parseRelative(t)
delta = timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second, microseconds=dt.microsecond).total_seconds()
elif d == 'A':
descriptor = Descriptor.ABSOLUTE
dt = parseAbsolute(t)
# See if timezone was specified. If not, use UTC
if dt.tzinfo != None:
print "Using timezone %s" % dt.tzinfo.tzname()
epoch = datetime.fromtimestamp(0, dt.tzinfo)
else:
print "Using UTC timezone"
epoch = datetime.utcfromtimestamp(0)
delta = (dt - epoch).total_seconds()
else:
__error(lineNumber, "Invalid time descriptor '" + d + "' found. Descriptor should either be 'A' for absolute times or 'R' for relative times")
seconds = int(delta)
useconds = int((delta - seconds) * 1000000)
return descriptor, seconds, useconds
# Open the sequence file and parse each line:
with open(seqfile, "r") as inputFile:
for i, line in enumerate(inputFile):
line = line.strip()
# ignore blank lines and comments
if line and line[0] != ';':
line = removeTrailingComments(line)
line = splitString(line)
length = len(line)
if length < 2:
__errorLine(i, "Each line must contain a minimum of two fields, time and command mnemonic\n")
else:
try:
descriptor, seconds, useconds = parseTime(i, line[0])
except:
__errorLine(i, "Encountered syntax error parsing timestamp")
mnemonic = line[1]
args = []
if length > 2:
args = line[2:]
try:
args = parseArgs(args)
except:
__errorLine(i, "Encountered sytax error parsing arguments")
yield i, descriptor, seconds, useconds, mnemonic, args
def generateSequence(inputFile, outputFile=None, generated_path, timebase):
'''
Write a binary sequence file from a text sequence file
@param inputFile: A text input sequence file name (usually a .seq extension)
@param outputFile: An output binary sequence file name (usually a .bin extension)
'''
# Check the user environment:
generated_command_path = generated_path + "/commands"
cmds = command_loader.CommandLoader.getInstance()
try:
cmds.create(generated_command_path)
except gseExceptions.GseControllerUndefinedDirectoryException:
__error("Environment variable 'GSE_GENERATED_PATH' is set to '" + generated_path + "'. This is not a valid directory. Make sure this variable is set correctly, and the GSE python deployment autocode as been installed in this location.")
# Parse the input file:
command_list = []
command_obj_dict = cmds.getCommandDict()
for i, descriptor, seconds, useconds, mnemonic, args in __parse(inputFile):
# Make sure that command is in the command dictionary:
if mnemonic in command_obj_dict:
command_obj = copy.deepcopy(command_obj_dict[mnemonic])
# Set the command arguments:
try:
command_obj.setArgs(args)
except ArgLengthMismatchException as e:
__errorLine(i, "'" + mnemonic + "' argument length mismatch. " + e.getMsg())
except TypeException as e:
__errorLine(i, "'" + mnemonic + "' argument type mismatch. " + e.getMsg())
# Set the command time and descriptor:
command_obj.setDescriptor(descriptor)
command_obj.setSeconds(seconds)
command_obj.setUseconds(useconds)
# Append this command to the command list:
command_list.append(command_obj)
else:
__errorLine(i, "'" + mnemonic + "' does not match any command in the command dictionary.")
# Write to the output file:
writer = SeqBinaryWriter(timebase=timebase)
if not outputFile:
outputFile = os.path.splitext(inputFile)[0] + ".bin"
try:
writer.open(outputFile)
except:
__error("Encountered problem opening output file '" + outputFile + "'.")
writer.write(command_list)
writer.close()
help_text = "seqgen.py -d"
if __name__ == "__main__":
'''
The main program if run from the command line. Note that this file can also be used
as a module by calling the generateSequence() function
'''
usage = "usage: %prog [options] input_file output_file"
parser = OptionParser(usage=usage)
parser.add_option("-g", "--generated_path", dest="generated_path", action="store", type="string", \
help="Set base path to generated command/telemetry definition files")
parser.add_option("-t", "--timebase", dest="timebase", action="store", type="string", default = None, \
help="Set base path to generated command/telemetry definition files [default: any]")
(opts, args) = parser.parse_args()
if opts.timebase == None:
timebase = 0xffff
else:
try:
timebase = int(opts.timebase,0)
except ValueError:
print("Could not parse time base %s"%opts.timebase)
sys.exit(-1)
if (len(args) == 1 or len(args) == 2) and good:
generateSequence(*args, generated_path=opts.generated_path,timebase=timebase)
else:
parser.print_help()
sys.exit(1)
sys.exit(0)

View File

@ -35,5 +35,5 @@ setenv OUTPUT_DIR `make -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk BUILD=$NATIV
echo "OUTPUT_DIR: ${OUTPUT_DIR}"
setenv LD_LIBRARY_PATH ${PYTHON_BASE}/lib
setenv PYTHONPATH ${BUILD_ROOT}/Gds/src
setenv PYTHONPATH ${BUILD_ROOT}/Gds
${PYTHON_BASE}/bin/python ${BUILD_ROOT}/Gds/bin/run_cmds.py $*

View File

@ -1,9 +0,0 @@
import time
cycle = 0
while True:
time.sleep(0.5)
print ("Cycle: %d"%cycle)
cycle = cycle + 1

View File

@ -15,7 +15,7 @@ def main(argv=None):
parser = OptionParser()
parser.add_option("-p", "--port", dest="port", action="store", type="int", help="Set the threaded TCP socket server port [default: %default]", default=50000)
parser.add_option("-a", "--addr", dest="addr", action="store", type="string", help="set the threaded TCP socket server address [default: %default]", default="localhost")
parser.add_option("-a", "--addr", dest="addr", action="store", type="string", help="set the threaded TCP socket server address [default: %default]", default="0.0.0.0")
parser.add_option("-n", "--nobin", dest="nobin", action="store_true", help="Disables the binary app from starting [default: %default]", default=False)
parser.add_option("-t", "--twin", dest="twin", action="store_true", help="Runs Threaed TCP Server in window, otherwise backgrounds [default: %default]", default=False)
@ -30,18 +30,18 @@ def main(argv=None):
# run ThreadedTCPServer
if twin:
TTS_args = [python_bin,"%s/Gse/bin/pexpect_runner.py"%build_root,"ThreadedTCP.log","Threaded TCP Server",python_bin,"%s/Gse/bin/ThreadedTCPServer.py"%build_root,"--port","%d"%used_port, "--host",addr]
TTS_args = [python_bin,"%s/Gds/tkGui/bin/pexpect_runner.py"%build_root,"ThreadedTCP.log","Threaded TCP Server",python_bin,"%s/Gse/bin/ThreadedTCPServer.py"%build_root,"--port","%d"%used_port, "--host",addr]
TTS = subprocess.Popen(TTS_args)
else:
tts_log = open("ThreadedTCP.log",'w')
TTS_args = [python_bin, "-u", "%s/Gse/bin/ThreadedTCPServer.py"%build_root,"--port","%d"%used_port, "--host",addr]
TTS_args = [python_bin, "-u", "%s/Gds/bin/ThreadedTCPServer.py"%build_root,"--port","%d"%used_port, "--host",addr]
TTS = subprocess.Popen(TTS_args,stdout=tts_log,stderr=subprocess.STDOUT)
# wait for TCP Server to start
time.sleep(2)
# run Gse GUI
GUI_args = [python_bin,"%s/Gse/bin/gse.py"%build_root,"--port","%d"%used_port,"--dictionary","%s/Gse/generated/Ref"%build_root,"--connect","--addr",addr,"-L","%s/Ref/logs"%build_root]
GUI_args = [python_bin,"%s/Gds/tkGui/bin/gse.py"%build_root,"--port","%d"%used_port,"--dictionary","%s/Ref/py_dict"%build_root,"--connect","--addr",addr,"-L","%s/Ref/logs"%build_root]
#print ("GUI: %s"%" ".join(GUI_args))
GUI = subprocess.Popen(GUI_args)
@ -52,7 +52,7 @@ def main(argv=None):
ref_bin = "%s/Ref/%s/Ref"%(build_root,os.environ["OUTPUT_DIR"])
if not nobin:
REF_args = [python_bin,"%s/Gse/bin/pexpect_runner.py"%build_root,"Ref.log","Ref Application",ref_bin,"-p","%d"%used_port,"-a",addr]
REF_args = [python_bin,"%s/Gds/tkGui/bin/pexpect_runner.py"%build_root,"Ref.log","Ref Application",ref_bin,"-p","%d"%used_port,"-a",addr]
REF = subprocess.Popen(REF_args)
GUI.wait()

View File

@ -25,6 +25,7 @@ export NATIVE_BUILD="`make -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk print_nat
echo "NATIVE_BUILD: ${NATIVE_BUILD}"
export OUTPUT_DIR="`make -f ${BUILD_ROOT}/mk/makefiles/build_vars.mk BUILD=$NATIVE_BUILD print_output_dir`"
echo "OUTPUT_DIR: ${OUTPUT_DIR}"
export PYTHONPATH="${BUILD_ROOT}/Gds"
echo "PYTHONPATH: ${PYTHONPATH}"
export PYTHONPATH="${BUILD_ROOT}/Gse/src"
python ${BUILD_ROOT}/Ref/scripts/run_ref.py "$@" &

View File

@ -16,15 +16,15 @@
|Event Name|ID|Description|Arg Name|Arg Type|Arg Size|Description
|---|---|---|---|---|---|---|
|UR_PortOpened|0 (0x0)|Connection opened| | | | |
| | | |port|U32|||
| | | |port|U32|||
|UR_SocketError|1 (0x1)|UDP port socket error| | | | |
| | | |error|Fw::LogStringArg&|80||
| | | |error|Fw::LogStringArg&|80||
|UR_BindError|2 (0x2)|UDP port socket error| | | | |
| | | |error|Fw::LogStringArg&|80||
| | | |error|Fw::LogStringArg&|80||
|UR_RecvError|3 (0x3)|UDP receive error| | | | |
| | | |error|Fw::LogStringArg&|80||
| | | |error|Fw::LogStringArg&|80||
|UR_DecodeError|4 (0x4)|Port decode error| | | | |
| | | |stage|DecodeStage|||
| | | |error|I32|||
| | | |stage|DecodeStage|||
| | | |error|I32|||
|UR_DroppedPacket|5 (0x5)|Dropped packet was detected| | | | |
| | | |diff|U32|||
| | | |diff|U32|||

View File

@ -14,9 +14,9 @@
|Event Name|ID|Description|Arg Name|Arg Type|Arg Size|Description
|---|---|---|---|---|---|---|
|US_PortOpened|0 (0x0)|Connection opened| | | | |
| | | |server|Fw::LogStringArg&|80||
| | | |port|U32|||
| | | |server|Fw::LogStringArg&|80||
| | | |port|U32|||
|US_SocketError|1 (0x1)|UDP port socket error| | | | |
| | | |error|Fw::LogStringArg&|80||
| | | |error|Fw::LogStringArg&|80||
|US_SendError|2 (0x2)|UDP send error| | | | |
| | | |error|Fw::LogStringArg&|80||
| | | |error|Fw::LogStringArg&|80||

View File

@ -210,5 +210,3 @@ OTHER_MODULES := \
DEPLOYMENTS := Ref acdev RPI
# Location of ground/gse software. Autocoded dictionary elements are copied here.
GDS_MODULE := Gse

View File

@ -103,54 +103,15 @@ comp_report_gen:
@$(CAT) ComponentReport.txt
dict_clean:
ifeq ($(DICT_GEN),"GLOBAL")
@echo "Cleaning dictionary in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable"
@$(RM_DIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable
else
@echo "Cleaning dictionary in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)"
@$(RM_DIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)
endif
@echo "Cleaning dictionary in $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable"
@$(RM_DIR) $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable
dict_install:
ifeq ($(DICT_GEN),"GLOBAL")
@echo "Installing instance dictionaries into $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable
@#@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events
@#@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels
@#@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable/__init__.py
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events/__init__.py
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels/__init__.py
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands/__init__.py
@#@$(CP) $(wildcard $(BUILD_ROOT)/Autocoders/Python/bin/'default_dict/channels/*.py) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels
@#@$(CP) $(wildcard $(BUILD_ROOT)/Autocoders/Python/bin/default_dict/events/*.py) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events
@#@$(CP) $(wildcard $(BUILD_ROOT)/Autocoders/Python/bin/default_dict/commands/*.py) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands
@#@$(CP_RECURSE) $(wildcard $(BUILD_ROOT)/Autocoders/Python/bin/default_dict/serializable) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)
@echo "Installing serializables in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable/__init__.py
@$(CP_RECURSE) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DICT_MODULE_SUBDIR)/serializable)) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)
else
@echo "Installing dictionaries into $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)"
@echo "Installing commands in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py
@$(CP) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DICT_MODULE_SUBDIR)/commands/*.py)) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/commands
@echo "Installing telemetry in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py
@$(CP) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DEFAULT_DICT_MODULE_SUBDIR)/channels/*.py)) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/channels
@echo "Installing events in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py
@$(CP) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DEFAULT_DICT_MODULE_SUBDIR)/events/*.py)) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/events
@echo "Installing serializables in $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable"
@$(MKDIR) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable
@$(TOUCH) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable/__init__.py
@$(CP_RECURSE) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)/serializable/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DEFAULT_DICT_MODULE_SUBDIR)/serializable)) $(BUILD_ROOT)/$(GDS_MODULE)/generated/$(DEPLOYMENT)
endif
@echo "Installing instance dictionaries into $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict"
@$(MKDIR) $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable
@$(TOUCH) $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable/__init__.py
@echo "Installing serializables in $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable"
@$(CP_RECURSE) $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict/serializable/__init__.py $(foreach module,$($(DEPLOYMENT)_MODULES),$(wildcard $(BUILD_ROOT)/$(module)/$(DICT_MODULE_SUBDIR)/serializable)) $(BUILD_ROOT)/$(DEPLOYMENT)/py_dict
gen_mod_sdds: $(foreach module,$($(DEPLOYMENT)_MODULES),$(subst /,,$(module))_sdd)