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

Feature/calendar with weather #70

Merged
merged 3 commits into from
Nov 18, 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
37 changes: 37 additions & 0 deletions src/alembic/versions/2023_11_18_2152-78f98d411652_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""empty message

Revision ID: 0ea1059c8f7c
Revises: 8bd32b7bb552
Create Date: 2023-11-18 21:52:58.786979

"""
from typing import Sequence, Union

import sqlalchemy as sa

from alembic import op


# revision identifiers, used by Alembic.
revision: str = "0ea1059c8f7c"
down_revision: Union[str, None] = "8bd32b7bb552"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("session", sa.Column("created_at", sa.DateTime(), nullable=False))
op.add_column("session", sa.Column("weather_code", sa.Integer(), nullable=False))
op.add_column("user", sa.Column("ido_longitude", sa.Float(), nullable=False))
op.add_column("user", sa.Column("keido_latitude", sa.Float(), nullable=False))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("user", "keido_latitude")
op.drop_column("user", "ido_longitude")
op.drop_column("session", "weather_code")
op.drop_column("session", "created_at")
# ### end Alembic commands ###
28 changes: 17 additions & 11 deletions src/kb_2315/backend/api/endpoints/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
from fastapi.responses import PlainTextResponse
from icalendar import Calendar, Event

from kb_2315.backend.crud import crud_sensor, crud_session, crud_shoe
from kb_2315.backend.crud import crud_session, crud_shoe
from kb_2315.backend.models import Session
from kb_2315.backend.weather.code2icon import weather_code2icon


router = APIRouter()
Expand All @@ -14,27 +15,32 @@
@router.get("/")
def get_calendar(shoe_id: int | None = None) -> PlainTextResponse:
JST = timezone(timedelta(hours=+9), "JST")
sessions: list[Session] = crud_session.search_session_by(shoe_id=shoe_id)

if shoe_id is None:
shoe_name: str = "靴"
sessions: list[Session] = crud_session.search_session_by()
else:
shoe_name = crud_shoe.search_shoe_by(shoe_id=shoe_id)[0].name
sessions = crud_session.search_session_by(shoe_id=shoe_id)
shoe_names: dict[int, str] = {}

def _search_shoes(shoe_id: int | None) -> str:
if shoe_id is None:
return "靴"
elif shoe_id in shoe_names.keys():
return shoe_names[shoe_id]
else:
shoe_names[shoe_id] = crud_shoe.search_shoe_by(shoe_id=shoe_id)[0].name
return shoe_names[shoe_id]

cal: Calendar = Calendar()
cal["summary"] = f"{shoe_name} の乾燥記録"
cal["summary"] = f"{_search_shoes(shoe_id=shoe_id)} の乾燥記録"
cal["scale"] = "GREGORIAN"
cal["method"] = "PUBLISH"
cal["X-WR-CALNAME"] = f"{shoe_name} の乾燥記録"
cal["X-WR-CALNAME"] = f"{_search_shoes(shoe_id=shoe_id)} の乾燥記録"
cal["X-WR-TIMEZONE"] = "Asia/Tokyo"

for s in sessions:
try:
last_time: datetime = crud_sensor.search_sensor_by(session_id=s.session_id)[0].time
last_time: datetime = s.created_at

e: Event = Event(
SUMMARY=f"{crud_shoe.search_shoe_by(shoe_id= s.shoe_id)[0].name} を履いた",
SUMMARY=f"天気: { weather_code2icon(s.weather_code)}, {_search_shoes(shoe_id=s.shoe_id)} を履いた",
DTSTART=datetime(
last_time.year, last_time.month, last_time.day, time(7, 0).hour, time(7, 0).minute, tzinfo=JST
)
Expand Down
19 changes: 14 additions & 5 deletions src/kb_2315/backend/api/endpoints/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from fastapi import APIRouter

from kb_2315 import notify
from kb_2315.backend.crud import crud_session
from kb_2315.backend.crud import crud_session, crud_user
from kb_2315.backend.models import User
from kb_2315.backend.schemas import schema_session
from kb_2315.config import conf

Expand All @@ -13,9 +14,17 @@

@router.get("/")
def create_session(device_id: int) -> schema_session.create_session:
session_id: UUID = crud_session.add_session(device_id=device_id)

notify.line.send_message(message=f"乾燥を開始しました\n{conf.host_url}/analyze/?session_id={session_id}\n\n靴を選んでください")
notify.line.shoe_select_carousel(session_id=session_id)
user: User = crud_user.search_user_by()[0]

session_id: UUID = crud_session.add_session(user=user, device_id=device_id)

notify.line.send_message(
message=f"乾燥を開始しました\n{conf.host_url}/analyze/?session_id={session_id}\n\n靴を選んでください",
send_to_id=user.line_channel_id,
)
notify.line.shoe_select_carousel(
session_id=session_id,
send_to_id=user.line_channel_id,
)

return schema_session.create_session(session_id=session_id)
6 changes: 4 additions & 2 deletions src/kb_2315/backend/crud/crud_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

from sqlalchemy.orm import Query

from kb_2315.backend.models import Session
from kb_2315.backend.models import Session, User
from kb_2315.backend.weather import api as weather_api

from .base_crud import base_CRUD


class CRUD_Session(base_CRUD):
def add_session(self, device_id: int, shoe_id: int | None = None) -> UUID:
def add_session(self, user: User, device_id: int, shoe_id: int | None = None) -> UUID:
with self._Session() as session:
new_session = Session()
new_session.shoe_id = shoe_id
new_session.device_id = device_id
new_session.weather_code = weather_api.get_weather_code(user.ido_longitude, user.keido_latitude)

session.add(new_session)
session.commit()
Expand Down
6 changes: 5 additions & 1 deletion src/kb_2315/backend/models/model_session.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import uuid
from datetime import datetime
from typing import TYPE_CHECKING
from uuid import UUID

from sqlalchemy import ForeignKey, Integer, Uuid
from sqlalchemy import DateTime, ForeignKey, Integer, Uuid
from sqlalchemy.orm import Mapped, mapped_column, relationship

from kb_2315.backend.db.base import Base
Expand All @@ -21,4 +22,7 @@ class Session(Base):
device_id: Mapped[int] = mapped_column(Integer, nullable=False)
shoe_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("shoe.id"), nullable=True)

weather_code: Mapped[int] = mapped_column(Integer, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)

sensors: Mapped[list[Sensor]] = relationship("Sensor", backref="event")
5 changes: 4 additions & 1 deletion src/kb_2315/backend/models/model_user.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sqlalchemy import Integer, String
from sqlalchemy import Float, Integer, String
from sqlalchemy.orm import Mapped, mapped_column

from kb_2315.backend.db.base import Base
Expand All @@ -8,3 +8,6 @@ class User(Base):
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String, default="Taro")
line_channel_id: Mapped[str] = mapped_column(String, nullable=True)

ido_longitude: Mapped[float] = mapped_column(Float, nullable=False)
keido_latitude: Mapped[float] = mapped_column(Float, nullable=False)
15 changes: 15 additions & 0 deletions src/kb_2315/backend/weather/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import requests


def get_weather_code(ido_longitude: float, keido_latitude: float) -> int:
url: str = (
f"https://api.open-meteo.com/v1/forecast?latitude={ido_longitude}&longitude={keido_latitude}"
"&timezone=Asia%2FTokyo&forecast_days&current=weather_code"
)

try:
r = requests.get(url).json()
return r.get("daily").get("weather_code")
except Exception:
# 困ったら曇り
return 2
45 changes: 45 additions & 0 deletions src/kb_2315/backend/weather/code2icon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
def weather_code2icon(weather_code: int) -> str:
"""
WMO 天気コードを4分類にする
https://open-meteo.com/en/docs
https://www.jodc.go.jp/data_format/weather-code_j.html#:~:text=%E7%8F%BE%E5%9C%A8%E5%A4%A9%E5%80%99(Present%20Weather)%20(WMO%20Code%204677)
"""
if weather_code in ["0", "1"]:
# 晴れ
return "☀"

elif weather_code in ["2", "3"]:
# 曇り
return "☁"

elif weather_code in [
# 雨
"45",
"48",
"51",
"53",
"55",
"56",
"57",
"61",
"63",
"65",
"66",
"67",
"80",
"81",
"82",
"95",
"96",
"99",
]:
return "🌧"

elif weather_code in ["71", "73", "75", "77", "85", "86"]:
# 雪
return "🌨"

# その他
else:
# その他,曇りとする
return "☁"