Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Key Error on analysis type and unlock packages #490

Merged
merged 2 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@
"backoff",
"click",
"dacite",
"fastapi-azure-auth==4.0.0",
"fastapi-azure-auth",
"fastapi",
"injector",
"opencensus-ext-logging",
"opencensus-ext-requests",
"opencensus-ext-azure",
"numpy",
"paho-mqtt",
"pydantic==1.10.11",
"pydantic",
"pydantic_settings",
"PyJWT",
"python-dotenv",
"PyYAML",
Expand Down
2 changes: 1 addition & 1 deletion src/isar/apis/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class StepResponse(BaseModel):

class TaskResponse(BaseModel):
id: str
tag_id: Optional[str]
tag_id: Optional[str] = None
aeshub marked this conversation as resolved.
Show resolved Hide resolved
steps: List[StepResponse]


Expand Down
14 changes: 7 additions & 7 deletions src/isar/apis/models/start_mission_definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@ class InspectionTypes(str, Enum):
class StartMissionInspectionDefinition(BaseModel):
type: InspectionTypes = Field(default=InspectionTypes.image)
inspection_target: InputPosition
duration: Optional[float]
metadata: Optional[dict]
id: Optional[str]
duration: Optional[float] = None
metadata: Optional[dict] = None
id: Optional[str] = None


class StartMissionTaskDefinition(BaseModel):
pose: InputPose
inspections: List[StartMissionInspectionDefinition]
tag: Optional[str]
id: Optional[str]
tag: Optional[str] = None
id: Optional[str] = None


class StartMissionDefinition(BaseModel):
tasks: List[StartMissionTaskDefinition]
id: Optional[str]
name: Optional[str]
id: Optional[str] = None
name: Optional[str] = None


def to_isar_mission(mission_definition: StartMissionDefinition) -> Mission:
Expand Down
90 changes: 50 additions & 40 deletions src/isar/config/settings.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import importlib.resources as pkg_resources
import os
from typing import List, Optional
from typing import Any, List, Optional

from dotenv import load_dotenv
from pydantic import BaseSettings, Field, validator
from pydantic import Field, ValidationInfo, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

from isar.config import predefined_missions
from robot_interface.models.robots.robot_model import RobotModel
from robot_interface.telemetry.payloads import VideoStream


class Settings(BaseSettings):
def __init__(self) -> None:
try:
with pkg_resources.path(f"isar.config", "settings.env") as path:
env_file_path = path
except ModuleNotFoundError:
env_file_path = None
super().__init__(_env_file=env_file_path)

# Determines which robot package ISAR will attempt to import
# Name must match with an installed python package in the local environment
ROBOT_PACKAGE: str = Field(default="isar_robot")
Expand All @@ -32,7 +41,7 @@ class Settings(BaseSettings):
FSM_SLEEP_TIME: float = Field(default=0.1)

# Location of JSON files containing predefined missions for the Local Planner to use
path = os.path.dirname(predefined_missions.__file__)
path: str = os.path.dirname(predefined_missions.__file__)
PREDEFINED_MISSIONS_FOLDER: str = Field(default=path + "/")

# Name of default map transformation
Expand Down Expand Up @@ -217,14 +226,18 @@ class Settings(BaseSettings):
DATA_CLASSIFICATION: str = Field(default="internal")

# List of MQTT Topics
TOPIC_ISAR_STATE: str = Field(default="state")
TOPIC_ISAR_MISSION: str = Field(default="mission")
TOPIC_ISAR_TASK: str = Field(default="task")
TOPIC_ISAR_STEP: str = Field(default="step")
TOPIC_ISAR_INSPECTION_RESULT = Field(default="inspection_result")
TOPIC_ISAR_ROBOT_STATUS: str = Field(default="robot_status")
TOPIC_ISAR_ROBOT_INFO: str = Field(default="robot_info")
TOPIC_ISAR_ROBOT_HEARTBEAT: str = Field(default="robot_heartbeat")
TOPIC_ISAR_STATE: str = Field(default="state", validate_default=True)
TOPIC_ISAR_MISSION: str = Field(default="mission", validate_default=True)
TOPIC_ISAR_TASK: str = Field(default="task", validate_default=True)
TOPIC_ISAR_STEP: str = Field(default="step", validate_default=True)
TOPIC_ISAR_INSPECTION_RESULT: str = Field(
default="inspection_result", validate_default=True
)
TOPIC_ISAR_ROBOT_STATUS: str = Field(default="robot_status", validate_default=True)
TOPIC_ISAR_ROBOT_INFO: str = Field(default="robot_info", validate_default=True)
TOPIC_ISAR_ROBOT_HEARTBEAT: str = Field(
default="robot_heartbeat", validate_default=True
)

# Logging

Expand Down Expand Up @@ -252,21 +265,22 @@ class Settings(BaseSettings):

REQUIRED_ROLE: str = Field(default="Mission.Control")

@validator("LOG_LEVELS", pre=True, always=True)
def set_log_levels(cls, v, values) -> dict:
@field_validator("LOG_LEVELS")
@classmethod
def set_log_levels(cls, v: Any, info: ValidationInfo) -> dict:
return {
"api": values["API_LOG_LEVEL"],
"main": values["MAIN_LOG_LEVEL"],
"mqtt": values["MQTT_LOG_LEVEL"],
"state_machine": values["STATE_MACHINE_LOG_LEVEL"],
"uploader": values["UPLOADER_LOG_LEVEL"],
"console": values["CONSOLE_LOG_LEVEL"],
"urllib3": values["URLLIB3_LOG_LEVEL"],
"uvicorn": values["UVICORN_LOG_LEVEL"],
"azure": values["AZURE_LOG_LEVEL"],
"api": info.data["API_LOG_LEVEL"],
"main": info.data["MAIN_LOG_LEVEL"],
"mqtt": info.data["MQTT_LOG_LEVEL"],
"state_machine": info.data["STATE_MACHINE_LOG_LEVEL"],
"uploader": info.data["UPLOADER_LOG_LEVEL"],
"console": info.data["CONSOLE_LOG_LEVEL"],
"urllib3": info.data["URLLIB3_LOG_LEVEL"],
"uvicorn": info.data["UVICORN_LOG_LEVEL"],
"azure": info.data["AZURE_LOG_LEVEL"],
}

@validator(
@field_validator(
"TOPIC_ISAR_STATE",
"TOPIC_ISAR_MISSION",
"TOPIC_ISAR_TASK",
Expand All @@ -275,20 +289,16 @@ def set_log_levels(cls, v, values) -> dict:
"TOPIC_ISAR_ROBOT_INFO",
"TOPIC_ISAR_ROBOT_HEARTBEAT",
"TOPIC_ISAR_INSPECTION_RESULT",
pre=True,
always=True,
)
def prefix_isar_topics(cls, v, values):
return f"isar/{values['ISAR_ID']}/{v}"

class Config:
with pkg_resources.path("isar.config", "settings.env") as path:
package_path = path

env_prefix = "ISAR_"
env_file = package_path
env_file_encoding = "utf-8"
case_sensitive = True
@classmethod
def prefix_isar_topics(cls, v: Any, info: ValidationInfo):
return f"isar/{info.data['ISAR_ID']}/{v}"

model_config = SettingsConfigDict(
env_prefix="ISAR_",
env_file_encoding="utf-8",
case_sensitive=True,
)


load_dotenv()
Expand Down Expand Up @@ -319,10 +329,10 @@ def __init__(self) -> None:
# Note that if the robot does not support moving an arm this will be None and
# the functionality will be unavailable
VALID_ARM_POSES: Optional[List[str]] = Field(default=None)

class Config:
env_file_encoding = "utf-8"
case_sensitive = True
model_config = SettingsConfigDict(
env_file_encoding="utf-8",
case_sensitive=True,
)


robot_settings = RobotSettings()
8 changes: 5 additions & 3 deletions src/isar/storage/slimm_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
from requests_toolbelt import MultipartEncoder

from isar.config.settings import settings
from robot_interface.models.mission.mission import Mission
from isar.services.auth.azure_credentials import AzureCredentials
from isar.services.service_connections.request_handler import RequestHandler
from isar.storage.storage_interface import StorageException, StorageInterface
from isar.storage.utilities import get_filename
from robot_interface.models.inspection.inspection import Inspection, ThermalVideo, Video
from robot_interface.models.mission.mission import Mission


class SlimmStorage(StorageInterface):
Expand Down Expand Up @@ -125,7 +125,8 @@ def _construct_multiform_request_image(
"ImageMetadata.AnalysisMethods": inspection.metadata.additional[
"analysis_type"
]
if inspection.metadata.additional["analysis_type"]
if inspection.metadata.additional
and inspection.metadata.additional["analysis_type"]
else "N/A",
"ImageMetadata.Description": str(inspection.metadata.additional),
"ImageMetadata.FunctionalLocation": inspection.metadata.tag_id # noqa: E501
Expand Down Expand Up @@ -172,7 +173,8 @@ def _construct_multiform_request_video(
"VideoMetadata.AnalysisMethods": inspection.metadata.additional[
"analysis_type"
]
if inspection.metadata.additional["analysis_type"]
if inspection.metadata.additional
and inspection.metadata.additional["analysis_type"]
else "N/A",
"VideoMetadata.Description": str(inspection.metadata.additional),
"VideoMetadata.FunctionalLocation": inspection.metadata.tag_id # noqa: E501
Expand Down
4 changes: 3 additions & 1 deletion src/isar/storage/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ def construct_metadata_file(
"mission_date": datetime.utcnow().date(),
"isar_id": settings.ISAR_ID,
"robot_name": settings.ROBOT_NAME,
"analysis_type": inspection.metadata.additional["analysis_type"],
"analysis_type": inspection.metadata.additional["analysis_type"]
if inspection.metadata.additional
else "N/A",
},
"data": [
{
Expand Down