SUML Poniższa dokumentacja opisuje aplikację serwera stworzoną przy użyciu FastAPI oraz integracji z Firebase (Firestore). Aplikacja zawiera m.in. mechanizmy rejestracji użytkownika, logowania, zarządzania posiłkami i składnikami oraz moduł do klasyfikacji i przewidywania kalorii ze zdjęcia.
Aplikacja pozwala na:
- Rejestrację i logowanie użytkowników (zabezpieczone hashem z użyciem biblioteki bcrypt).
- Dodawanie i aktualizowanie posiłków wraz z kaloriami.
- Dodawanie składników do wybranych posiłków.
- Przegląd posiłków przypisanych do danego użytkownika (w formie listy).
- Klasyfikację obrazu (zdjęcia) i szacowanie wartości kalorycznej przy użyciu modeli Fastai.
- Całość działa w oparciu o bazę Google Firestore.
- Python w wersji 3.8+ (sprawdzony na 3.9 i 3.10)
- Zależności pakietów Python podane w requirements.txt
- Konto w Firebase z włączoną bazą Firestore oraz wygenerowany plik klucza serwisowego (firebase-key.json).
├── models/
│ ├── classification_model.pkl
│ └── regression_model.pkl
├── firebase-key.json
├── main.py
├── requirements.txt
- models/ – katalog przechowujący modele Fastai:
- classification_model.pkl – model używany do klasyfikacji obrazu
- regression_model.pkl – model używany do szacowania kalorii
- firebase-key.json – plik klucza serwisowego Firebase (uwaga: nie zalecane jest commitowanie tego pliku do repozytorium publicznego — patrz Zabezpieczenia i uwagi).
- main.py – główny plik, kod serwera.
- requirements.txt – lista zależności.
Wejdź na console.firebase.google.com i utwórz nowy projekt.
Włącz Cloud Firestore (tryb natywny — production lub testowy).
W ustawieniach projektu Firebase znajdź sekcję Service accounts.
Wygeneruj nowy private key i umieść go w projekcie.
Upewnij się, że ścieżka do firebase-key.json w kodzie jest prawidłowa.
pip install -r requirements.txt
- classification_model.pkl
- regression_model.pkl
uvicorn <nazwa_pliku>:app --reload
Endpoint: POST /register
Parametry:
- email:
str - password:
str
Zwraca:
userId: ID wygenerowanego użytkownika- Wiadomość o pomyślnym dodaniu użytkownika
Endpoint: POST /token
Parametry:
- username:
str(email użytkownika) - password:
str
Zwraca:
access_token: token (w tym przypadku ID użytkownika w Firestore)token_type:bearer
Important
W kolejnych endpointach wymagane jest podanie tokenu w nagłówku:
Authorization: Bearer <access_token>
Endpoint: POST /add-meal
Parametry:
- name:
str(nazwa posiłku) - calories:
int(liczba kalorii, np. 300) - time:
datetime(np. 2025-01-01T12:00:00; jeśli brak, przyjmowana jest bieżąca data) - file:
UploadFile(opcjonalnie, obrazek posiłku)
Nagłówek: Authorization: Bearer <token>
Zwraca:
mealId: ID dodanego posiłku- komunikat o pomyślnym dodaniu
Endpoint: PUT /update-meal/{meal_id}
Parametry:
name:str(opcjonalnie)calories:int(opcjonalnie)time:datetime(opcjonalnie)file:UploadFile(opcjonalnie, aktualizacja zdjęcia)
Nagłówek: Authorization: Bearer <token>
Zwraca: komunikat o pomyślnym zaktualizowaniu danych
Endpoint: POST /add-ingredients/{meal_id}
Parametry:
ingredients: lista obiektów[{"name": str, "calories": int}, ...]
Nagłówek: Authorization: Bearer <token>
Zwraca:
- identyfikatory dodanych składników
- zaktualizowaną łączną liczbę kalorii
Endpoint: GET /meals
Nagłówek: Authorization: Bearer <token>
Zwraca: listę obiektów reprezentujących posiłki z bazy (z uwzględnieniem zdekodowanego zdjęcia w formacie base64, jeśli istnieje).
Endpoint: POST /classify
Parametry:
file:UploadFile(wymagane — obraz do klasyfikacji)
Zwraca:
predicted_class: nazwa przewidywanej klasy (str)probability: prawdopodobieństwo przewidzianej klasy (float)estimated_calories: przewidywana wartość kaloryczna (float)
-
Hasła użytkowników są przechowywane w bazie jako hash (bcrypt). Dzięki temu nawet jeśli dojdzie do wycieku bazy, rzeczywiste hasła nie zostaną ujawnione wprost.
-
Token w tym projekcie jest uproszczony — użytkownik otrzymuje w polu
access_tokenwartość odpowiadającą jego dokumentowi w Firestore. W rzeczywistej aplikacji produkcyjnej zaleca się:- Stosowanie JWT lub innego bardziej zaawansowanego mechanizmu autentykacji.
- Używanie HTTPS w celu ochrony danych przesyłanych do serwera.
-
Plik
firebase-key.json(klucz serwisowy Firebase) nie powinien być publikowany w repozytorium publicznym. Najlepiej użyć zmiennych środowiskowych lub prywatnego repozytorium / menedżera sekretów (np. w chmurze). -
Mechanizm przechowywania obrazów w bazie Firestore (w polu
image) jest mało optymalny przy większej skali. Najlepszym rozwiązaniem jest przechowywanie plików w Firebase Storage lub podobnym rozwiązaniu i trzymanie jedynie linków do nich.
Rozszerzalność: Aplikacja serwera demonstruje główne koncepcje — w projekcie produkcyjnym warto dodać np. obsługę wyjątków, logowanie, ograniczenia i sprawdzanie zapytań, poprawić zapytania, ujednolicić nazwy parametrów i zmiennych, etc.
Poniższa dokumentacja opisuje przykładową aplikację React Native. Aplikacja obsługuje logowanie, rejestrowanie, wykonywanie zdjęć, klasyfikację potraw (w oparciu o endpoint serwera) oraz tworzenie i przeglądanie posiłków wraz z ich kaloriami.
Aplikacja pozwala użytkownikom:
- Logować się i rejestrować (endpointy serwera).
- Tworzyć posiłki (z nazwą, kaloriami i zdjęciem).
- Przeglądać posiłki zebrane w bazie (z podziałem na daty, kalorie, itp.).
- Robić zdjęcia w aplikacji i przesyłać je do serwera w celu klasyfikacji (dostajemy przewidywaną klasę potrawy i przybliżoną wartość kaloryczną).
- Nawigować pomiędzy ekranami (Home, Camera, Meal Creation itp.) za pomocą React Navigation.
Poniżej uproszczona struktura projektu (część plików konfiguracyjnych pominięta):
├── app
│ ├── screens
│ │ ├── LoginScreen.tsx
│ │ ├── HomeScreen.tsx
│ │ ├── CameraScreen.tsx
│ │ └── MealCreationScreen.tsx
│ ├── services
│ │ ├── auth.ts
│ │ ├── add_meal.ts
│ │ ├── classify_image.ts
│ │ └── meals.ts
│ ├── styles
│ │ └── style.ts
│ ├── types
│ │ └── index.ts
│ └── config.ts
└── ...
- AppNavigator.tsx – definiuje nawigację pomiędzy ekranami.
- LoginScreen.tsx – ekran logowania i rejestracji.
- HomeScreen.tsx – główny ekran z listą posiłków.
- CameraScreen.tsx – pozwala na zrobienie zdjęcia i klasyfikację.
- MealCreationScreen.tsx – pozwala na stworzenie nowego posiłku (nazwa, kalorie itp.).
- services – pliki komunikujące się z serwerem (autentykacja, tworzenie/odczyt posiłków, klasyfikacja).
- config.ts – przechowuje np. adres serwera (
SERVER_URL).
- Node.js
- React Native
- W projekcie używane są m.in.:
expo-camera,expo-file-systemreact-navigationluxon(do obsługi dat)
- W pliku
config.tsnależy określić adres serweraSERVER_URL, np.:
export const SERVER_URL = 'http://192.168.0.10:8000';
- Stack.Navigator – definiuje stos ekranów.
- Aplikacja startuje na ekranie "Login".
- Nazwy ekranów to "Login", "Home", "CameraScreen", "MealCreationScreen".
- Wykorzystuje CameraView z expo-camera do robienia zdjęcia.
- Po zrobieniu zdjęcia (takePhoto) plik jest zapisywany lokalnie (FileSystem), a następnie wysyłany do serwera przez classifyImage.
- Po uzyskaniu wyniku klasyfikacji (klasa i przybliżone kalorie) można przejść do ekranu MealCreationScreen.
- Wyświetla listę posiłków pobranych z serwera (getMeals).
- Grupuje posiłki według daty i pokazuje łączną liczbę kalorii.
- Zawiera przycisk przenoszący do CameraScreen w celu dodania nowego zdjęcia/posiłku.
- Pozwala się zalogować (funkcja login) lub zarejestrować (register).
- Po poprawnym logowaniu zapisuje authToken w AsyncStorage i przenosi na ekran Home.
- Przyjmuje w parametrze photoUri i wynik klasyfikacji (klasa, kalorie).
- Użytkownik może zmienić nazwę, wprowadzić kalorie, ustawić datę/godzinę.
- Po zapisaniu do serwera (addMeal) wraca na ekran Home.
worzy FormData z plikiem zdjęcia (photoUri) i danymi posiłku
Wysyła zapytanie POST /add-meal do serwera z tokenem w nagłówku
Wysyła POST /token (username & password).
Zwraca access_token (ID użytkownika).
Wysyła POST /register (email & password).
Wysyła POST /classify z danymi obrazu (FormData)
Oczekuje w odpowiedzi predicted_class, estimated_calories
Wysyła GET /meals (token w nagłówku)
Dekoduje zdjęcia (base64) i zapisuje je w plikach lokalnych
Zwraca listę posiłków (z polami: id, name, calories, time, image)
Jest to pierwsza i bardzo poglądowa wersja aplikacji, która zapewnia podstawową funkcjonalność.