Skip to content

Commit 69fe608

Browse files
committed
refactor(data_model_vehicle_components): Separate into base, templates, import and validation
This makes it simpler to test and keeps the linters happier Make the GNSS protocol depend on the GNSS connection type Restrict the RC receiver, telemetry and battery protocols depending on the selected FC connection type Improve and simplify the data validation code Update protocol choices when the type changes and is written. The cell voltage now changes when chemistry changes The TOW limits are checked against each other Validate the dict constants used to validate the data Re-use common fixatures to prevent code duplication
1 parent 40c29ad commit 69fe608

16 files changed

+5776
-2242
lines changed

ardupilot_methodic_configurator/backend_filesystem_vehicle_components.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,93 @@ def _check_references(self, schema_obj: dict[str, Any], property_name: str) -> t
631631

632632
return False, schema_obj
633633

634+
def get_all_value_datatypes(self) -> dict[str, Any]:
635+
"""
636+
Get a dictionary of all value data types used in the vehicle_components_dict as defined in the schema.
637+
638+
The keys are the vehicle_components_dict keys and their values are the actual Python datatype
639+
640+
:return: A nested dictionary mapping data names to their Python datatypes.
641+
"""
642+
schema = self.load_schema()
643+
if not schema:
644+
return {}
645+
646+
value_datatypes: dict[str, Any] = {}
647+
648+
# Start with the Components node since all our editable items are under it
649+
components_schema = schema.get("properties", {}).get("Components", {})
650+
if not components_schema:
651+
return {}
652+
653+
# Traverse all component types (Flight Controller, Frame, etc.)
654+
for component_type, component_schema in components_schema.get("properties", {}).items():
655+
value_datatypes[component_type] = {}
656+
self._extract_datatypes_from_component(component_schema, value_datatypes[component_type])
657+
658+
return value_datatypes
659+
660+
def _extract_datatypes_from_component(self, component_schema: dict[str, Any], target_dict: dict[str, Any]) -> None:
661+
"""Extract datatypes from a component schema recursively."""
662+
# Resolve reference if present
663+
resolved_schema = self._resolve_schema_reference(component_schema)
664+
665+
# Check direct properties
666+
if "properties" in resolved_schema:
667+
for prop_name, prop_schema in resolved_schema["properties"].items():
668+
self._extract_datatypes_from_property(prop_schema, prop_name, target_dict)
669+
670+
# Check allOf constructs
671+
if "allOf" in resolved_schema:
672+
for allof_item in resolved_schema["allOf"]:
673+
self._extract_datatypes_from_component(allof_item, target_dict)
674+
675+
def _extract_datatypes_from_property(
676+
self, prop_schema: dict[str, Any], prop_name: str, target_dict: dict[str, Any]
677+
) -> None:
678+
"""Extract datatype from a property schema."""
679+
# Resolve reference if present
680+
resolved_schema = self._resolve_schema_reference(prop_schema)
681+
682+
# If this property has nested properties, create a nested dict and recurse
683+
if "properties" in resolved_schema:
684+
target_dict[prop_name] = {}
685+
for nested_prop_name, nested_prop_schema in resolved_schema["properties"].items():
686+
self._extract_datatypes_from_property(nested_prop_schema, nested_prop_name, target_dict[prop_name])
687+
688+
# Handle allOf constructs in properties
689+
elif "allOf" in resolved_schema:
690+
target_dict[prop_name] = {}
691+
for allof_item in resolved_schema["allOf"]:
692+
self._extract_datatypes_from_property(allof_item, prop_name, target_dict)
693+
694+
# If this property has a direct type, convert to Python type and record it as a leaf value
695+
elif "type" in resolved_schema:
696+
target_dict[prop_name] = self._json_type_to_python_type(resolved_schema["type"])
697+
698+
# If no type or properties found, create empty dict as placeholder
699+
else:
700+
target_dict[prop_name] = {}
701+
702+
def _json_type_to_python_type(self, json_type: str) -> type:
703+
"""
704+
Convert JSON Schema type string to actual Python type.
705+
706+
:param json_type: JSON Schema type string
707+
:return: Corresponding Python type
708+
"""
709+
type_mapping = {
710+
"string": str,
711+
"number": float,
712+
"integer": int,
713+
"boolean": bool,
714+
"array": list,
715+
"object": dict,
716+
"null": type(None),
717+
}
718+
719+
return type_mapping.get(json_type, str) # Default to str if unknown type
720+
634721

635722
def main() -> None:
636723
"""Main function for standalone execution."""

0 commit comments

Comments
 (0)