Skip to content

Commit

Permalink
Add database infrastructure and mock db
Browse files Browse the repository at this point in the history
  • Loading branch information
anetteu authored and vetlek committed Jan 21, 2022
1 parent b88711b commit 831e528
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 6 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

frontend/node_modules/
venv/
.vscode
8 changes: 2 additions & 6 deletions backend/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="flotilla",
version='0.0.0',
version="0.0.0",
description="Backend for the Flotilla application",
long_description=open("README.md").read(),
long_description_content_type="text/markdown",
Expand All @@ -19,11 +19,7 @@
"Topic :: Scientific/Engineering :: Physics",
],
include_package_data=True,
install_requires=[
"fastapi",
"uvicorn",
"requests",
],
install_requires=["fastapi", "uvicorn", "requests", "SQLAlchemy", "pytz"],
extras_require={
"dev": [
"pytest",
Expand Down
Empty file added backend/src/flotilla/api/api.py
Empty file.
Empty file.
12 changes: 12 additions & 0 deletions backend/src/flotilla/database/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:"

engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
124 changes: 124 additions & 0 deletions backend/src/flotilla/database/mock_database/mock_database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import datetime

from flotilla.database.models import (
Capability,
Entry,
EntryStatus,
Event,
InspectionType,
Report,
ReportStatus,
Robot,
RobotStatus,
)


def populate_mock_db(session, engine, base) -> None:
base.metadata.create_all(engine)

robot_1 = Robot(
name="Harald",
model="King",
serial_number="VI",
logs="",
status=RobotStatus.available,
)

robot_2 = Robot(
name="Harold",
model="King",
serial_number="VII",
logs="",
status=RobotStatus.offline,
)

session.add_all([robot_1, robot_2])
session.commit()

report_1 = Report(
robot_id=robot_1.id,
isar_mission_id="isar_mission_id",
echo_mission_id=1,
log="",
status=ReportStatus.in_progress,
)
report_2 = Report(
robot_id=robot_2.id,
isar_mission_id="isar_mission_id",
echo_mission_id=1,
log="",
status=ReportStatus.completed,
)

session.add(report_1, report_2)
session.commit()

entry_1 = Entry(
report_id=report_1.id,
tag_id="tag_id",
status=EntryStatus.completed,
inspection_type=InspectionType.image,
time=datetime.datetime.now(tz=datetime.timezone.utc),
file_location="",
)

entry_2 = Entry(
report_id=report_2.id,
tag_id="tag_id",
status=EntryStatus.failed,
inspection_type=InspectionType.thermal_image,
time=datetime.datetime.now(tz=datetime.timezone.utc),
file_location="",
)

entry_3 = Entry(
report_id=report_2.id,
tag_id="tag_id",
status=EntryStatus.completed,
inspection_type=InspectionType.image,
time=datetime.datetime.now(tz=datetime.timezone.utc),
file_location="",
)

event_1 = Event(
robot_id=robot_1.id,
echo_mission_id=287,
report_id=report_1.id,
estimated_duration=datetime.timedelta(hours=1),
)

event_2 = Event(
robot_id=robot_2.id,
echo_mission_id=287,
report_id=report_2.id,
estimated_duration=datetime.timedelta(hours=2),
)

capability_1 = Capability(
robot_id=robot_2.id,
capability=InspectionType.image,
)

capability_2 = Capability(
robot_id=robot_2.id,
capability=InspectionType.thermal_image,
)

capability_3 = Capability(
robot_id=robot_1.id,
capability=InspectionType.image,
)

session.add_all(
[
entry_1,
entry_2,
entry_3,
event_1,
event_2,
capability_1,
capability_2,
capability_3,
]
)
session.commit()
113 changes: 113 additions & 0 deletions backend/src/flotilla/database/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import datetime
import enum

from sqlalchemy import Column, DateTime, Enum, ForeignKey, Integer, Interval, String
from sqlalchemy.orm import backref, relationship

from flotilla.database.db import Base


class RobotStatus(enum.Enum):
available = "Available"
busy = "Busy"
offline = "Offline"


class InspectionType(enum.Enum):
image = "Image"
thermal_image = "ThermalImage"


class ReportStatus(enum.Enum):
scheduled = "Scheduled"
in_progress = "InProgress"
failed = "Failed"
completed = "Completed"


class EntryStatus(enum.Enum):
failed = "Failed"
completed = "Completed"


class Robot(Base):
__tablename__ = "robot"
id = Column(Integer, primary_key=True)
name = Column(String)
model = Column(String)
serial_number = Column(String)
logs = Column(String)
status = Column(Enum(RobotStatus))
telemetry_topics = relationship("Topic", backref=backref("robot"))
streams = relationship("VideoStream", backref=backref("robot"))
capabilities = relationship("Capability", backref=backref("robot"))
events = relationship("Event", backref=backref("robot"))


class Report(Base):
__tablename__ = "report"
id = Column(Integer, primary_key=True)
robot_id = Column(Integer, ForeignKey("robot.id"))
isar_mission_id = Column(String)
echo_mission_id = Column(Integer)
log = Column(String)
status = Column(Enum(ReportStatus))
entries = relationship("Entry", backref=backref("report"))


class Map(Base):
__tablename__ = "map"
id = Column(Integer, primary_key=True)
location = Column(String)
coordinate_reference_system = Column(String)
# grid = Column(String)


class Topic(Base):
__tablename__ = "topic"
id = Column(Integer, primary_key=True)
robot_id = Column(Integer, ForeignKey("robot.id"))
name = Column(String)


class VideoStream(Base):
__tablename__ = "video_stream"
id = Column(Integer, primary_key=True)
robot_id = Column(Integer, ForeignKey("robot.id"))
rtsp_url = Column(String)
port = Column(Integer)
camera_name = Column(String)


class Capability(Base):
__tablename__ = "capability"
id = Column(Integer, primary_key=True)
robot_id = Column(Integer, ForeignKey("robot.id"))
capability = Column(Enum(InspectionType))


class Event(Base):
__tablename__ = "event"
id = Column(Integer, primary_key=True)
robot_id = Column(Integer, ForeignKey("robot.id"))
echo_mission_id = Column(Integer)
report_id = Column(Integer, ForeignKey("report.id"))
start_time = Column(
DateTime(timezone=True), default=datetime.datetime.now(tz=datetime.timezone.utc)
)
estimated_duration = Column(Interval)
# foreign_key_constraint = ForeignKeyConstraint()
# TODO: robot_id and report_id.robot_id can now point at different robots. Should there be a constraint forcing an event to point at only one robot?


class Entry(Base):
__tablename__ = "entry"
id = Column(Integer, primary_key=True)
report_id = Column(Integer, ForeignKey("report.id"))
tag_id = Column(String)
status = Column(Enum(EntryStatus))
inspection_type = Column(Enum(InspectionType))
time = Column(
DateTime(timezone=True), default=datetime.datetime.now(tz=datetime.timezone.utc)
)
file_location = Column(String)
1 change: 1 addition & 0 deletions backend/src/flotilla/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

app = FastAPI()


@app.get("/")
async def root():
return {"message": "Hello World"}
12 changes: 12 additions & 0 deletions backend/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pytest
from sqlalchemy.orm import Session

from flotilla.database.db import Base, SessionLocal, engine
from flotilla.database.mock_database.mock_database import populate_mock_db

mock_session: Session = SessionLocal()
populate_mock_db(session=mock_session,engine=engine,base=Base)

@pytest.fixture()
def session() -> Session:
return mock_session
5 changes: 5 additions & 0 deletions backend/tests/test_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from flotilla.database.models import Robot


def test_mock_db(session):
assert len(session.query(Robot.name).all()) == 2

0 comments on commit 831e528

Please sign in to comment.