Skip to content

Commit

Permalink
Add fprime param json to seq/dat file converter
Browse files Browse the repository at this point in the history
  • Loading branch information
Zimri Leisher committed Jan 28, 2025
1 parent b4c4122 commit 7e09597
Show file tree
Hide file tree
Showing 3 changed files with 399 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/fprime_gds/common/loaders/prm_json_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"""
prm_json_loader.py:
Loads flight dictionary (JSON) and returns id and mnemonic based Python dictionaries of params
@author zimri.leisher
"""

from fprime_gds.common.templates.prm_template import PrmTemplate
from fprime_gds.common.loaders.json_loader import JsonLoader
from fprime_gds.common.data_types.exceptions import GdsDictionaryParsingException


class PrmJsonLoader(JsonLoader):
"""Class to load parameters from json dictionaries"""

PARAMS_FIELD = "parameters"

ID = "id"
NAME = "name"
TYPE = "type"
DESC = "annotation"
DEFAULT = "default"


def construct_dicts(self, _):
"""
Constructs and returns python dictionaries keyed on id and name
Args:
_: Unused argument (inherited)
Returns:
A tuple with two channel dictionaries (python type dict):
(id_dict, fqn_name_dict). The keys should be the channels' id and
fully qualified name fields respectively and the values should be PrmTemplate
objects.
"""
id_dict = {}
fqn_name_dict = {}

if self.PARAMS_FIELD not in self.json_dict:
raise GdsDictionaryParsingException(
f"Ground Dictionary missing '{self.PARAMS_FIELD}' field: {str(self.json_file)}"
)

for prm_dict in self.json_dict[self.PARAMS_FIELD]:
# Create a channel template object
prm_temp = self.construct_template_from_dict(prm_dict)

id_dict[prm_temp.get_id()] = prm_temp
fqn_name_dict[prm_temp.get_full_name()] = prm_temp

return (
dict(sorted(id_dict.items())),
dict(sorted(fqn_name_dict.items())),
self.get_versions(),
)

def construct_template_from_dict(self, prm_dict: dict) -> PrmTemplate:
try:
prm_id = prm_dict[self.ID]
# The below assignment also raises a ValueError if the name does not contain a '.'
qualified_component_name, prm_name = prm_dict[self.NAME].rsplit('.', 1)
if not qualified_component_name or not prm_name:
raise ValueError()

type_obj = self.parse_type(prm_dict[self.TYPE])
except ValueError as e:
raise GdsDictionaryParsingException(
f"Parameter dictionary entry malformed, expected name of the form '<QUAL_COMP_NAME>.<PRM_NAME>' in : {str(prm_dict)}"
)
except KeyError as e:
raise GdsDictionaryParsingException(
f"{str(e)} key missing from parameter dictionary entry or its associated type in the dictionary: {str(prm_dict)}"
)

prm_default_val = prm_dict.get(self.DEFAULT, None)

return PrmTemplate(
prm_id,
prm_name,
qualified_component_name,
type_obj,
prm_default_val
)
81 changes: 81 additions & 0 deletions src/fprime_gds/common/templates/prm_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
@brief Params Template class
Instances of this class describe a parameter of a component instance (not
including a specific value)
@date Created January 27, 2025
@author Zimri Leisher
@bug Hopefully none
"""

from fprime.common.models.serialize.type_base import BaseType
from fprime.common.models.serialize.type_exceptions import TypeMismatchException

from . import data_template


class PrmTemplate(data_template.DataTemplate):
"""Class for param templates that describe parameters of component instances"""

def __init__(
self,
prm_id: int,
prm_name: str,
comp_name: str,
prm_type_obj: BaseType,
prm_default_val,
):
"""
Constructor
Args:
prm_id: the id of the parameter
prm_name: the name of the parameter
comp_name: the name of the component instance owning this parameter
prm_type_obj: the instance of BaseType corresponding to the type of this parameter
prm_default_val: the default value of this parameter, in raw JSON form
"""
super().__init__()
# Make sure correct types are passed
if not isinstance(prm_id, int):
raise TypeMismatchException(int, type(prm_id))

if not isinstance(prm_name, str):
raise TypeMismatchException(str, type(prm_name))

if not isinstance(comp_name, str):
raise TypeMismatchException(str, type(comp_name))

if not issubclass(prm_type_obj, BaseType):
raise TypeMismatchException(BaseType, prm_type_obj)

# prm_default_val is an arbitrary type, likely a primitive or dict

self.prm_id = prm_id
self.prm_name = prm_name
self.comp_name = comp_name
self.prm_type_obj = prm_type_obj
self.prm_default_val = prm_default_val

def get_full_name(self):
"""
Get the full name of this param
Returns:
The full name (component.param) for this param
"""
return f"{self.comp_name}.{self.prm_name}"

def get_id(self):
return self.prm_id

def get_name(self):
return self.prm_name

def get_comp_name(self):
return self.comp_name

def get_type_obj(self):
return self.prm_type_obj
Loading

0 comments on commit 7e09597

Please sign in to comment.