184 lines
5.4 KiB
Markdown
184 lines
5.4 KiB
Markdown
# Smart App City — Backend Architecture Proposal
|
|
|
|
## Overview
|
|
Backend Python FastAPI + JWT pour l'application mobile Smart City Martinique.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
api-gateway/ → Point d'entrée unique, rate limiting, CORS
|
|
auth-service/ → Inscription, login, JWT, gestion utilisateurs
|
|
iot-service/ → Données capteurs, alertes, historique
|
|
gis-service/ → Données géospatiales, couches, géocodage
|
|
notification-service/ → Notifications push, alertes
|
|
reporting-service/ → Rapports, statistiques, export PDF
|
|
```
|
|
|
|
## Tech Stack
|
|
- **Framework** : FastAPI (async, OpenAPI auto, Pydantic)
|
|
- **Auth** : JWT (python-jose) + bcrypt (passlib)
|
|
- **DB** : PostgreSQL (existant) + SQLModel (ORM)
|
|
- **Cache** : Redis (existant)
|
|
- **Messages** : MQTT (Mosquitto existant) pour temps réel
|
|
- **Notifications** : Firebase Cloud Messaging (FCM)
|
|
- **Maps** : Tuiles vectorielles OpenStreetMap
|
|
|
|
## API Endpoints (MVP)
|
|
|
|
### Auth Service (`/api/v1/auth`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| POST | `/register` | Inscription utilisateur |
|
|
| POST | `/login` | Login → JWT tokens |
|
|
| POST | `/refresh` | Refresh access token |
|
|
| GET | `/me` | Profil utilisateur |
|
|
| PUT | `/me` | Modifier profil |
|
|
| POST | `/logout` | Invalider token |
|
|
|
|
### IoT Service (`/api/v1/iot`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/sensors` | Liste des capteurs |
|
|
| GET | `/sensors/{id}` | Détail capteur |
|
|
| GET | `/sensors/{id}/data` | Données historiques |
|
|
| GET | `/zones` | Zones de la ville |
|
|
| GET | `/zones/{id}/sensors` | Capteurs par zone |
|
|
| GET | `/alerts` | Alertes actives |
|
|
| GET | `/stats` | Statistiques globales |
|
|
|
|
### GIS Service (`/api/v1/gis`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/layers` | Couches disponibles |
|
|
| GET | `/layers/{id}/features` | Features d'une couche |
|
|
| GET | `/search` | Recherche d'adresse |
|
|
| GET | `/reverse` | Géocodage inversé |
|
|
|
|
### Reporting Service (`/api/v1/reports`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/daily` | Rapport journalier |
|
|
| GET | `/weekly` | Rapport hebdomadaire |
|
|
| GET | `/custom` | Rapport personnalisé |
|
|
| GET | `/export/pdf` | Export PDF |
|
|
|
|
### Notification Service (`/api/v1/notifications`)
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/` | Notifications utilisateur |
|
|
| PUT | `/read/{id}` | Marquer comme lu |
|
|
| POST | `/register-device` | Enregistrer token FCM |
|
|
| GET | `/preferences` | Préférences notifications |
|
|
|
|
## Data Models
|
|
|
|
### User
|
|
```python
|
|
class User(BaseModel):
|
|
id: UUID
|
|
email: str
|
|
username: str
|
|
hashed_password: str
|
|
first_name: str
|
|
last_name: str
|
|
phone: Optional[str]
|
|
role: UserRole # admin, user, viewer
|
|
avatar_url: Optional[str]
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
```
|
|
|
|
### Sensor
|
|
```python
|
|
class Sensor(BaseModel):
|
|
id: UUID
|
|
name: str
|
|
type: SensorType # temperature, humidity, air_quality, traffic, noise
|
|
status: SensorStatus # active, inactive, maintenance, error
|
|
location: GeoPoint # [lng, lat]
|
|
zone_id: Optional[UUID]
|
|
last_reading: Optional[Reading]
|
|
battery_level: Optional[int]
|
|
created_at: datetime
|
|
```
|
|
|
|
### Reading
|
|
```python
|
|
class Reading(BaseModel):
|
|
id: UUID
|
|
sensor_id: UUID
|
|
value: float
|
|
unit: str
|
|
timestamp: datetime
|
|
quality: float # 0-1 data quality score
|
|
```
|
|
|
|
### Alert
|
|
```python
|
|
class Alert(BaseModel):
|
|
id: UUID
|
|
sensor_id: UUID
|
|
type: AlertType # threshold_offline, anomaly
|
|
severity: AlertSeverity # low, medium, high, critical
|
|
message: str
|
|
value: Optional[float]
|
|
threshold: Optional[float]
|
|
status: AlertStatus # active, acknowledged, resolved
|
|
created_at: datetime
|
|
resolved_at: Optional[datetime]
|
|
```
|
|
|
|
## Services Structure (per service)
|
|
|
|
Each service follows this structure:
|
|
```
|
|
service-name/
|
|
├── Dockerfile
|
|
├── requirements.txt
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── main.py # FastAPI app entry
|
|
│ ├── config.py # Settings, env vars
|
|
│ ├── database.py # DB connection, session
|
|
│ ├── models/ # SQLModel models
|
|
│ │ ├── __init__.py
|
|
│ │ └── models.py
|
|
│ ├── schemas/ # Pydantic schemas
|
|
│ │ ├── __init__.py
|
|
│ │ └── schemas.py
|
|
│ ├── routes/ # API routes
|
|
│ │ ├── __init__.py
|
|
│ │ └── routes.py
|
|
│ ├── services/ # Business logic
|
|
│ │ ├── __init__.py
|
|
│ │ └── service.py
|
|
│ └── auth/ # JWT verification
|
|
│ ├── __init__.py
|
|
│ └── jwt.py
|
|
└── tests/
|
|
├── __init__.py
|
|
└── test_routes.py
|
|
```
|
|
|
|
## Deployment Options
|
|
|
|
### Option A: Single Container (simplifié)
|
|
Tous les services dans un seul container FastAPI avec des routers séparés.
|
|
- Plus simple à déployer
|
|
- Moins de ressources
|
|
- Idéal pour MVP
|
|
|
|
### Option B: Multi-containers (microservices réel)
|
|
Chaque service dans son propre container.
|
|
- Plus scalable
|
|
- Plus complexe à gérer
|
|
- Nécessite Docker Compose
|
|
|
|
**Recommandation MVP** : Option A (single container avec routers), puis refactor en microservices si besoin.
|
|
|
|
## Next Steps
|
|
1. Choisir Option A ou B
|
|
2. Créer le backend complet
|
|
3. Intégrer avec le frontend Expo existant
|
|
4. Déployer sur le serveur
|