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

Add database #32

Merged
merged 1 commit into from
Jan 21, 2022
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
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.
14 changes: 14 additions & 0 deletions backend/src/flotilla/database/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# TODO: Move to config
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()
148 changes: 148 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,148 @@
import datetime
import resource

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


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

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

robot_2 = Robot(
name="Haakon",
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,
)

topic_1 = Topic(
robot_id=robot_1.id,
path="/robot_1/pose",
resource=Resource.pose
)

topic_2 = Topic(
robot_id=robot_1.id,
path="/robot_1/battery",
resource=Resource.battery
)

topic_3 = Topic(
robot_id=robot_2.id,
path="/robot_2/pressure",
resource=Resource.pressure
)

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

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):
in_progress = "InProgress"
failed = "Failed"
completed = "Completed"


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

class Resource(enum.Enum):
pose = "pose"
battery = "battery"
pressure = "pressure"


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)


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


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)
# 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