Refactor code structure for improved readability and maintainability
This commit is contained in:
56
diagrams/architecture.puml
Normal file
56
diagrams/architecture.puml
Normal file
@@ -0,0 +1,56 @@
|
||||
@startuml architecture_timelapse
|
||||
|
||||
' Configuration pour rendre le diagramme plus compact
|
||||
skinparam padding 1
|
||||
skinparam nodesep 5
|
||||
skinparam ranksep 1
|
||||
skinparam componentMargin 1
|
||||
skinparam packagePadding 2
|
||||
skinparam defaultTextAlignment center
|
||||
skinparam linetype ortho
|
||||
skinparam rectangle {
|
||||
borderColor transparent
|
||||
stereotypeBorderColor transparent
|
||||
}
|
||||
|
||||
!$ICONURL = "https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/v3.0.0/icons"
|
||||
!include $ICONURL/common.puml
|
||||
!include $ICONURL/devicons/javascript.puml
|
||||
!include $ICONURL/devicons/html5.puml
|
||||
!include $ICONURL/devicons/css3.puml
|
||||
!include $ICONURL/devicons/nodejs.puml
|
||||
!include $ICONURL/devicons/postgresql.puml
|
||||
|
||||
package "Hôte Proxmox" {
|
||||
package "Conteneur LXC" as lxc {
|
||||
package "Frontend" as frontend {
|
||||
DEV_HTML5(html, "HTML5")
|
||||
DEV_CSS3(css, "CSS3") #line:transparent
|
||||
DEV_JAVASCRIPT(js, "JavaScript") #line:transparent
|
||||
}
|
||||
|
||||
package "Backend" as backend {
|
||||
DEV_NODEJS(express, "ExpressJS") #line:transparent
|
||||
[FFmpeg] as ffmpeg #line:transparent
|
||||
note right of ffmpeg: Image vers Vidéo
|
||||
}
|
||||
|
||||
database "Base de données" as db {
|
||||
DEV_POSTGRESQL(pg, "PostgreSQL") #line:transparent
|
||||
note right of pg: Timelapses & Données
|
||||
}
|
||||
|
||||
frontend --> backend : HTTP/REST
|
||||
backend --> db : Requêtes
|
||||
backend --> ffmpeg : Traitement
|
||||
}
|
||||
|
||||
storage "Réplication Ceph" as ceph {
|
||||
[Stockage de données] as storage #line:transparent
|
||||
note right of storage: Stockage distribué
|
||||
}
|
||||
|
||||
lxc --> ceph : Stockage
|
||||
}
|
||||
|
||||
@enduml
|
||||
77
diagrams/backend/backend1.puml
Normal file
77
diagrams/backend/backend1.puml
Normal file
@@ -0,0 +1,77 @@
|
||||
@startuml Modèles de données
|
||||
|
||||
class Project {
|
||||
+id: integer
|
||||
+name: string
|
||||
+description: string
|
||||
+start_date: date
|
||||
+status: integer
|
||||
+getAllProjects()
|
||||
+getProjectById(id)
|
||||
+createProject(name, description, startDate, status)
|
||||
+updateProject(id, updates)
|
||||
+updateProjectStatus(id, status)
|
||||
+deleteProject(id)
|
||||
+findCurrentRenderingProject()
|
||||
+findStoppingProject()
|
||||
}
|
||||
|
||||
class Measurement {
|
||||
+id: integer
|
||||
+project_id: integer
|
||||
+timestamp: datetime
|
||||
+path: string
|
||||
+temperature: float
|
||||
+humidity: float
|
||||
+order_id: integer
|
||||
+getAllMeasurements()
|
||||
+getMeasurementById(id)
|
||||
+getMeasurementByProjectAndOrderId(projectId, orderId)
|
||||
+getMeasurementsByProjectId(projectId)
|
||||
+createMeasurement(projectId, timestamp, path, temperature, humidity, orderId)
|
||||
+updateMeasurement(id, updates)
|
||||
+deleteMeasurement(id)
|
||||
+getNextOrderId(projectId)
|
||||
}
|
||||
|
||||
class Video {
|
||||
+id: integer
|
||||
+project_id: integer
|
||||
+measurement_ids: string
|
||||
+name: string
|
||||
+resolution: string
|
||||
+duration: integer
|
||||
+status: integer
|
||||
+progress: float
|
||||
+video_file: string
|
||||
+started_at: datetime
|
||||
+updated_at: datetime
|
||||
+eta: float
|
||||
+getAllVideos()
|
||||
+getVideoById(id)
|
||||
+getVideosByProjectId(projectId)
|
||||
+createVideo(projectId, measurementIds, name, resolution, duration, status)
|
||||
+updateVideo(id, updates)
|
||||
+updateVideoFilePath(id, videoFile)
|
||||
+updateVideoStatus(id, status)
|
||||
+deleteVideo(id)
|
||||
+getUnfinishedVideos()
|
||||
+updateVideoProgress(id, progress, eta)
|
||||
}
|
||||
|
||||
class Camera {
|
||||
+id: integer
|
||||
+interval: integer
|
||||
+maintenance: integer
|
||||
+active: integer
|
||||
+getCamera()
|
||||
+updateCamera(id, updates)
|
||||
+deleteCamera(id)
|
||||
+initializeCamera()
|
||||
}
|
||||
|
||||
Project "1" -- "0..*" Measurement : possède >
|
||||
Project "1" -- "0..*" Video : possède >
|
||||
Measurement "1..*" -- "0..*" Video : utilisée dans >
|
||||
|
||||
@enduml
|
||||
62
diagrams/backend/backend2.puml
Normal file
62
diagrams/backend/backend2.puml
Normal file
@@ -0,0 +1,62 @@
|
||||
@startuml Architecture MVC
|
||||
|
||||
package "Controllers" {
|
||||
[ProjectController]
|
||||
[MeasurementController]
|
||||
[VideoController]
|
||||
[ImageController]
|
||||
[CameraController]
|
||||
}
|
||||
|
||||
package "Models" {
|
||||
[Project]
|
||||
[Measurement]
|
||||
[Video]
|
||||
[Camera]
|
||||
[DatabaseManager]
|
||||
}
|
||||
|
||||
package "Routes" {
|
||||
[projectRoutes]
|
||||
[measurementRoutes]
|
||||
[videoRoutes]
|
||||
[imageRoutes]
|
||||
[cameraRoutes]
|
||||
[index]
|
||||
}
|
||||
|
||||
package "Services" {
|
||||
[StorageService]
|
||||
[VideoService]
|
||||
}
|
||||
|
||||
package "Utils" {
|
||||
[errorHandler]
|
||||
}
|
||||
|
||||
package "Database" {
|
||||
[connection]
|
||||
}
|
||||
|
||||
package "Config" {
|
||||
[config]
|
||||
}
|
||||
|
||||
cloud "Client" {
|
||||
[Frontend]
|
||||
}
|
||||
|
||||
[Frontend] --> [Routes]
|
||||
[Routes] --> [Controllers]
|
||||
[Controllers] --> [Models]
|
||||
[Controllers] --> [Services]
|
||||
[Models] --> [Database]
|
||||
[Services] --> [Models]
|
||||
[Controllers] --> [Utils]
|
||||
[Models] --> [Utils]
|
||||
[Services] --> [Utils]
|
||||
[Models] --> [Config]
|
||||
[Services] --> [Config]
|
||||
[Controllers] --> [Config]
|
||||
|
||||
@enduml
|
||||
39
diagrams/backend/backend3.puml
Normal file
39
diagrams/backend/backend3.puml
Normal file
@@ -0,0 +1,39 @@
|
||||
@startuml Création de vidéo
|
||||
|
||||
actor Client
|
||||
participant "videoRoutes" as Routes
|
||||
participant "VideoController" as Controller
|
||||
participant "Video" as Model
|
||||
participant "Measurement" as MeasurementModel
|
||||
participant "VideoService" as Service
|
||||
participant "FFmpeg" as FFmpeg
|
||||
database Database
|
||||
|
||||
Client -> Routes: POST /videos
|
||||
Routes -> Controller: createVideo(req, res)
|
||||
Controller -> Model: createVideo(project_id, measurement_ids, name, resolution, duration)
|
||||
Model -> Database: INSERT INTO videos
|
||||
Database --> Model: video data
|
||||
Model --> Controller: video object
|
||||
|
||||
Controller -> Controller: getMeasurementPathList(measurement_ids, project_id)
|
||||
Controller -> MeasurementModel: getMeasurementByProjectAndOrderId(projectId, orderId)
|
||||
MeasurementModel -> Database: SELECT * FROM measurements
|
||||
Database --> MeasurementModel: measurement data
|
||||
MeasurementModel --> Controller: measurement object with path
|
||||
|
||||
Controller -> Service: createVideoFromImages(project_id, pathList, duration, video_id, resWidth, resHeight)
|
||||
Service -> FFmpeg: spawn('ffmpeg', ffmpegArgs)
|
||||
Service -> Model: updateVideo(videoId, {status: rendering, progress: 0})
|
||||
Model -> Database: UPDATE videos SET status = rendering, progress = 0
|
||||
FFmpeg --> Service: stderr progress events
|
||||
Service -> Model: updateVideoProgress(videoId, progress, eta)
|
||||
Model -> Database: UPDATE videos SET progress = X, eta = Y
|
||||
FFmpeg --> Service: process complete
|
||||
Service -> Model: updateVideo(videoId, {status: completed, progress: 100})
|
||||
Model -> Database: UPDATE videos SET status = completed, progress = 100
|
||||
Service --> Controller: videoFile path
|
||||
Controller --> Routes: { message: success, id: video.id }
|
||||
Routes --> Client: 200 OK - JSON Response
|
||||
|
||||
@enduml
|
||||
34
diagrams/backend/backend4.puml
Normal file
34
diagrams/backend/backend4.puml
Normal file
@@ -0,0 +1,34 @@
|
||||
@startuml Cas d'utilisation
|
||||
|
||||
left to right direction
|
||||
actor "Utilisateur" as User
|
||||
actor "Caméra" as Camera
|
||||
|
||||
rectangle "Timelapse Backend" {
|
||||
usecase "Gérer les projets" as UC1
|
||||
usecase "Configurer la caméra" as UC2
|
||||
usecase "Capturer des images" as UC3
|
||||
usecase "Créer des vidéos" as UC4
|
||||
usecase "Visualiser les images" as UC5
|
||||
usecase "Visualiser les vidéos" as UC6
|
||||
usecase "Démarrer une capture" as UC7
|
||||
usecase "Arrêter une capture" as UC8
|
||||
usecase "Uploader une image et des mesures" as UC9
|
||||
|
||||
UC1 ..> UC7 : <<include>>
|
||||
UC1 ..> UC8 : <<include>>
|
||||
UC2 ..> UC7 : <<extend>>
|
||||
UC2 ..> UC8 : <<extend>>
|
||||
UC3 ..> UC9 : <<include>>
|
||||
UC4 ..> UC5 : <<include>>
|
||||
}
|
||||
|
||||
User --> UC1
|
||||
User --> UC2
|
||||
User --> UC4
|
||||
User --> UC5
|
||||
User --> UC6
|
||||
Camera --> UC3
|
||||
Camera --> UC9
|
||||
|
||||
@enduml
|
||||
41
diagrams/backend/backend5.puml
Normal file
41
diagrams/backend/backend5.puml
Normal file
@@ -0,0 +1,41 @@
|
||||
@startuml Déploiement
|
||||
|
||||
node "Client Device" {
|
||||
[Web Browser] as Browser
|
||||
}
|
||||
|
||||
node "Docker Environment" {
|
||||
node "timelapse-api" {
|
||||
[Express Server] as Server
|
||||
[Node.js Runtime] as Node
|
||||
[FFmpeg] as FFmpeg
|
||||
}
|
||||
|
||||
database "timelapse-db" {
|
||||
[PostgreSQL] as DB
|
||||
}
|
||||
|
||||
folder "Volumes" {
|
||||
folder "storage/" {
|
||||
[Project Images]
|
||||
[Generated Videos]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node "Camera Device" {
|
||||
[Camera Software] as CamSoftware
|
||||
[Sensors] as Sensors
|
||||
}
|
||||
|
||||
Browser --> Server: HTTP/REST
|
||||
CamSoftware --> Server: HTTP/REST
|
||||
Server --> DB: SQL Queries
|
||||
Server --> FFmpeg: Process Spawn
|
||||
FFmpeg --> [Project Images]: Read
|
||||
FFmpeg --> [Generated Videos]: Write
|
||||
Server --> [Project Images]: Read/Write
|
||||
Server --> [Generated Videos]: Read
|
||||
Sensors --> CamSoftware: Temperature/\nHumidity Data
|
||||
|
||||
@enduml
|
||||
42
diagrams/frontend/frontend1.puml
Normal file
42
diagrams/frontend/frontend1.puml
Normal file
@@ -0,0 +1,42 @@
|
||||
@startuml
|
||||
|
||||
class Project {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
status: number
|
||||
start_date: date
|
||||
}
|
||||
|
||||
class Measurement {
|
||||
id: number
|
||||
project_id: number
|
||||
order_id: number
|
||||
timestamp: string
|
||||
temperature: number
|
||||
humidity: number
|
||||
}
|
||||
|
||||
class Video {
|
||||
id: number
|
||||
project_id: number
|
||||
name: string
|
||||
measurement_ids: string
|
||||
resolution: string
|
||||
duration: number
|
||||
status: number
|
||||
}
|
||||
|
||||
class CameraController {
|
||||
active_project_id: number
|
||||
start_timelapse(id, frequency, nbimages): void
|
||||
stopCamera(id): void
|
||||
manualUpload(imageFile, projectId, timestamp, temperature, humidity): void
|
||||
}
|
||||
|
||||
Project "1" *-- "n" Measurement : contient
|
||||
Project "1" *-- "n" Video : contient
|
||||
Measurement "n" o-- "n" Video : utilisées dans
|
||||
CameraController -- Video : génère
|
||||
|
||||
@enduml
|
||||
19
diagrams/frontend/frontend2.puml
Normal file
19
diagrams/frontend/frontend2.puml
Normal file
@@ -0,0 +1,19 @@
|
||||
@startuml
|
||||
|
||||
start
|
||||
:Créer un projet;
|
||||
:Configurer la caméra;
|
||||
:Prises d'images automatiques;
|
||||
|
||||
fork
|
||||
:Upload manuel d'images;
|
||||
fork again
|
||||
:Arrêt de la caméra;
|
||||
end fork
|
||||
|
||||
:Sélection des images;
|
||||
:Générer une vidéo;
|
||||
:Visualiser les données;
|
||||
stop
|
||||
|
||||
@enduml
|
||||
20
diagrams/frontend/frontend3.puml
Normal file
20
diagrams/frontend/frontend3.puml
Normal file
@@ -0,0 +1,20 @@
|
||||
@startuml
|
||||
|
||||
actor Browser
|
||||
participant Frontend
|
||||
participant API
|
||||
participant Camera
|
||||
|
||||
Browser -> Frontend : 1. Create project
|
||||
Frontend -> API : 2. POST /projects
|
||||
Browser -> Frontend : 3. Configure camera
|
||||
Frontend -> API : 4. POST /procedure/start
|
||||
API -> Camera : 4. Start capturing
|
||||
Camera --> API : 5. Capture images
|
||||
Browser -> Frontend : 6. Create video request
|
||||
Frontend -> API : 7. POST /videos
|
||||
Browser -> Frontend : 8. Render video
|
||||
Frontend -> API : 9. POST /videos/render/{id}
|
||||
Frontend --> Browser : 10. Display video & metrics
|
||||
|
||||
@enduml
|
||||
28
diagrams/frontend/frontend4.puml
Normal file
28
diagrams/frontend/frontend4.puml
Normal file
@@ -0,0 +1,28 @@
|
||||
@startuml
|
||||
|
||||
left to right direction
|
||||
actor "Utilisateur" as user
|
||||
|
||||
rectangle "Système Timelapse" {
|
||||
usecase "Gérer les projets" as UC1
|
||||
usecase "Configurer la caméra" as UC2
|
||||
usecase "Créer des vidéos" as UC3
|
||||
usecase "Visualiser les données" as UC4
|
||||
usecase "Uploader manuellement" as UC5
|
||||
usecase "Afficher métriques" as UC6
|
||||
|
||||
UC1 --> UC2
|
||||
UC2 --> UC3
|
||||
UC1 --> UC4
|
||||
UC2 --> UC5
|
||||
UC3 --> UC6
|
||||
}
|
||||
|
||||
user --> UC1
|
||||
user --> UC2
|
||||
user --> UC3
|
||||
user --> UC4
|
||||
user --> UC5
|
||||
user --> UC6
|
||||
|
||||
@enduml
|
||||
29
diagrams/frontend/frontend5.puml
Normal file
29
diagrams/frontend/frontend5.puml
Normal file
@@ -0,0 +1,29 @@
|
||||
@startuml
|
||||
|
||||
node "Client Browser" {
|
||||
[HTML/CSS/JS]
|
||||
[JQuery]
|
||||
[Chart.js]
|
||||
}
|
||||
|
||||
node "Backend API" {
|
||||
[RESTful Services]
|
||||
[Image Processing]
|
||||
[Video Generation]
|
||||
}
|
||||
|
||||
database "Filesystem Storage" {
|
||||
[Images]
|
||||
[Videos]
|
||||
}
|
||||
|
||||
node "Camera Controller" {
|
||||
[Capture Configuration]
|
||||
[Sensors (temp/humid)]
|
||||
}
|
||||
|
||||
[HTML/CSS/JS] -- [RESTful Services] : HTTP
|
||||
[RESTful Services] -- [Filesystem Storage]
|
||||
[RESTful Services] -- [Camera Controller]
|
||||
|
||||
@enduml
|
||||
@@ -1,4 +1,4 @@
|
||||
@startuml Architecture Globale
|
||||
@startuml global
|
||||
|
||||
' Définition des composants
|
||||
node "Interfaces utilisateur" {
|
||||
|
||||
100
diagrams/global_interspec.puml
Normal file
100
diagrams/global_interspec.puml
Normal file
@@ -0,0 +1,100 @@
|
||||
@startuml
|
||||
left to right direction
|
||||
|
||||
skinparam component {
|
||||
BackgroundColor<<Informatique>> #FFE4B5
|
||||
BackgroundColor<<Électronique>> #98FB98
|
||||
BackgroundColor<<Matériaux>> #87CEEB
|
||||
BorderColor #333
|
||||
}
|
||||
|
||||
package "Infrastructure Globale" {
|
||||
component "Caméra Raspberry Pi" <<Électronique>> as pi {
|
||||
component "Module Caméra" as cam
|
||||
component "Scripts Capture" as scripts
|
||||
}
|
||||
|
||||
component "Serveur Central" <<Informatique>> as server {
|
||||
component "Backend (Node.js/Express)" as backend
|
||||
component "FFMPEG Processing" as ffmpeg
|
||||
component "Base de Données" as db
|
||||
}
|
||||
|
||||
component "Interface Web" <<Informatique>> as web {
|
||||
component "Frontend (HTML/CSS/JS)" as front
|
||||
component "Nginx Reverse Proxy" as nginx
|
||||
}
|
||||
|
||||
component "Application Android" <<Informatique>> as android {
|
||||
component "Kotlin API" as kotlin
|
||||
component "Glide Image Processing" as glide
|
||||
}
|
||||
|
||||
component "Système Énergétique" <<Électronique>> as energy {
|
||||
component "Microcontrôleur STM32" as stm
|
||||
component "Batterie LiPo" as battery
|
||||
component "Panneau Solaire" as solar
|
||||
}
|
||||
|
||||
component "Boîtier Mécanique" <<Matériaux>> as box {
|
||||
component "Structure Étanche" as structure
|
||||
component "Système Fixation" as mount
|
||||
}
|
||||
|
||||
component "Infrastructure Virtualisée" <<Informatique>> as infra {
|
||||
component "Proxmox VE" as proxmox
|
||||
component "VM Ubuntu" as vm
|
||||
component "Docker Containers" as docker
|
||||
}
|
||||
}
|
||||
|
||||
pi --> server : "Transfert images\n(HTTP/MQTT)"
|
||||
server --> web : "API REST"
|
||||
server --> android : "API REST"
|
||||
energy --> pi : "Alimentation\n(Power Management)"
|
||||
energy --> stm : "Contrôle énergie"
|
||||
box --> pi : "Protection physique"
|
||||
box --> energy : "Intégration"
|
||||
infra --> server : "Hébergement"
|
||||
infra --> web : "Hébergement"
|
||||
cam --> scripts : "Capture RAW"
|
||||
scripts --> backend : "Envoi images"
|
||||
backend --> ffmpeg : "Conversion vidéo"
|
||||
ffmpeg --> db : "Stockage"
|
||||
stm --> battery : "Monitoring"
|
||||
solar --> battery : "Recharge"
|
||||
front --> nginx : "Requêtes"
|
||||
nginx --> backend : "Proxy"
|
||||
vm --> docker : "Orchestration"
|
||||
structure --> mount : "Assemblage"
|
||||
|
||||
note top of pi
|
||||
**Technologies Électronique**
|
||||
- Altium Designer
|
||||
- STM32 CubeIDE
|
||||
- Protocoles I2C/SPI
|
||||
end note
|
||||
|
||||
note right of server
|
||||
**Stack Logicielle**
|
||||
- Node.js + Express
|
||||
- PostgreSQL
|
||||
- FFMPEG
|
||||
- CI/CD Gitea
|
||||
end note
|
||||
|
||||
note left of energy
|
||||
**Gestion Énergie**
|
||||
- PCB Custom
|
||||
- Capteurs température/hygro
|
||||
- Algorithme économie d'énergie
|
||||
end note
|
||||
|
||||
note bottom of box
|
||||
**Caractéristiques Mécaniques**
|
||||
- PLA résistant aux UV
|
||||
- Indice IP67
|
||||
- Dissipation thermique
|
||||
end note
|
||||
|
||||
@enduml
|
||||
87
diagrams/global_interspec_lite.puml
Normal file
87
diagrams/global_interspec_lite.puml
Normal file
@@ -0,0 +1,87 @@
|
||||
@startuml
|
||||
left to right direction
|
||||
|
||||
skinparam component {
|
||||
BackgroundColor<<Logiciel>> #FFE4B5
|
||||
BackgroundColor<<Matériel>> #98FB98
|
||||
BackgroundColor<<Infrastructure>> #87CEEB
|
||||
BorderColor #333
|
||||
}
|
||||
|
||||
package "Matériel" <<Matériel>> {
|
||||
component "RPi 4B + Cam" as pi {
|
||||
[Module Caméra] --> [Scripts Python]
|
||||
}
|
||||
|
||||
component "Système d'énergie" as energy {
|
||||
[STM32] --> [Batterie LiPo]
|
||||
[Panneau Solaire] --> [Gestion d'énergie]
|
||||
}
|
||||
|
||||
component "Boîtier Mécanique" as box {
|
||||
[PLA IP67] --> [Système de Montage]
|
||||
}
|
||||
}
|
||||
|
||||
package "Logiciel" <<Logiciel>> {
|
||||
component "Backend" as backend {
|
||||
[Node.js] --> [FFMPEG]
|
||||
[Express] --> [PostgreSQL]
|
||||
}
|
||||
|
||||
component "Frontend" as web {
|
||||
[React] --> [Nginx]
|
||||
}
|
||||
|
||||
component "Application Mobile" as mobile {
|
||||
[Kotlin] --> [Android API]
|
||||
}
|
||||
}
|
||||
|
||||
package "Infrastructure" <<Infrastructure>> {
|
||||
component "Proxmox" as proxmox {
|
||||
[VM Ubuntu] --> [Docker]
|
||||
}
|
||||
}
|
||||
|
||||
pi --> backend : "HTTP/MQTT\n(images)"
|
||||
energy --> pi : "Alimentation"
|
||||
box --> pi : "Protection physique"
|
||||
backend --> web : "API REST"
|
||||
backend --> mobile : "API REST"
|
||||
proxmox --> backend : "Hébergement"
|
||||
proxmox --> web : "Proxy inverse"
|
||||
|
||||
note right of pi
|
||||
<b>Technologie Matérielle:</b>
|
||||
• Altium Designer
|
||||
• STM32 CubeIDE
|
||||
• I2C/SPI
|
||||
• RDM6/CES
|
||||
end note
|
||||
|
||||
note bottom of backend
|
||||
<b>Stack Logicielle:</b>
|
||||
• Node.js/Express
|
||||
• FFMPEG
|
||||
• Auth JWT
|
||||
• CI/CD Gitea
|
||||
end note
|
||||
|
||||
note left of proxmox
|
||||
<b>Infrastructure:</b>
|
||||
• Docker Swarm
|
||||
• Let's Encrypt
|
||||
• VPN/Wireguard
|
||||
• Sauvegardes Automatisées
|
||||
end note
|
||||
|
||||
note top of box
|
||||
<b>Mécanique:</b>
|
||||
• Solidworks
|
||||
• BambuLab X1
|
||||
• Analyse Thermique
|
||||
• Classification IP67
|
||||
end note
|
||||
|
||||
@enduml
|
||||
52
diagrams/raspi/01_architecture_generale.puml
Normal file
52
diagrams/raspi/01_architecture_generale.puml
Normal file
@@ -0,0 +1,52 @@
|
||||
@startuml Architecture Générale du Système Timelapse
|
||||
|
||||
!define ICONURL https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/v2.4.0
|
||||
!include ICONURL/common.puml
|
||||
!include ICONURL/devicons/python.puml
|
||||
!include ICONURL/font-awesome-5/raspberry_pi.puml
|
||||
!include ICONURL/font-awesome-5/cloud.puml
|
||||
!include ICONURL/font-awesome-5/camera.puml
|
||||
!include ICONURL/font-awesome-5/database.puml
|
||||
|
||||
skinparam {
|
||||
BackgroundColor white
|
||||
ArrowColor #666666
|
||||
BorderColor #666666
|
||||
FontName "Arial"
|
||||
}
|
||||
|
||||
rectangle "Système Raspberry Pi" as raspi {
|
||||
DEV_PYTHON(pyonline, "timelapse_online.py") #lightblue
|
||||
DEV_PYTHON(pyoffline, "timelapse_offline.py") #lightgreen
|
||||
rectangle "timelapse/" {
|
||||
DEV_PYTHON(config, "config.py") #lightyellow
|
||||
DEV_PYTHON(apiclient, "api_client.py") #pink
|
||||
DEV_PYTHON(capture, "capture.py") #lightcyan
|
||||
DEV_PYTHON(sensors, "sensors.py") #lightyellow
|
||||
}
|
||||
FA5_DATABASE(localdb, "CONFIG/config.json") #lightgrey
|
||||
FA5_CAMERA(camera, "Caméra") #white
|
||||
}
|
||||
|
||||
cloud "Serveur Distant" {
|
||||
rectangle "API REST" as api #pink
|
||||
database "Base de données" as db #lightgrey
|
||||
}
|
||||
|
||||
pyonline --> config : utilise
|
||||
pyoffline --> config : utilise
|
||||
pyonline --> apiclient : utilise
|
||||
pyonline --> capture : utilise
|
||||
pyoffline --> capture : utilise
|
||||
capture --> config : lit/écrit
|
||||
capture --> sensors : utilise
|
||||
apiclient --> api : communique
|
||||
config --> localdb : lit/écrit
|
||||
sensors --> camera : contrôle
|
||||
|
||||
note bottom of pyonline : "Mode connecté"
|
||||
note bottom of pyoffline : "Mode hors ligne"
|
||||
note right of api : "Authentification\net gestion des données"
|
||||
note bottom of camera : "Capture des images"
|
||||
|
||||
@enduml
|
||||
77
diagrams/raspi/02_flux_capture.puml
Normal file
77
diagrams/raspi/02_flux_capture.puml
Normal file
@@ -0,0 +1,77 @@
|
||||
@startuml Flux du Processus de Capture d'Images
|
||||
|
||||
skinparam {
|
||||
BackgroundColor white
|
||||
ArrowColor #666666
|
||||
BorderColor #666666
|
||||
FontName "Arial"
|
||||
}
|
||||
|
||||
start
|
||||
if (Connexion internet disponible?) then (oui)
|
||||
:Mode connecté (timelapse_online.py);
|
||||
:Récupération du statut depuis l'API;
|
||||
if (Serveur accessible?) then (oui)
|
||||
:Mise à jour de la configuration locale;
|
||||
if (Mode maintenance?) then (oui)
|
||||
:Arrêt du processus;
|
||||
stop
|
||||
else (non)
|
||||
if (Demande d'arrêt?) then (oui)
|
||||
:Confirmation de l'arrêt au serveur;
|
||||
:Réinitialisation de la configuration;
|
||||
stop
|
||||
else (non)
|
||||
if (Configuration active?) then (oui)
|
||||
:Capture d'image;
|
||||
:Lecture des données environnementales;
|
||||
:Envoi au serveur;
|
||||
if (Envoi réussi?) then (oui)
|
||||
:Décrémenter le nombre d'images restantes;
|
||||
else (non)
|
||||
:Sauvegarder en mode hors-ligne;
|
||||
endif
|
||||
if (Toutes images capturées?) then (oui)
|
||||
:Notification au serveur;
|
||||
:Désactivation de la configuration;
|
||||
stop
|
||||
else (non)
|
||||
:Attente du prochain cycle;
|
||||
endif
|
||||
else (non)
|
||||
:Mode IDLE, aucune action;
|
||||
stop
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
else (non)
|
||||
:Fonctionnement en mode dégradé;
|
||||
endif
|
||||
else (non)
|
||||
:Mode hors ligne (timelapse_offline.py);
|
||||
if (Configuration active?) then (oui)
|
||||
if (Images restantes > 0?) then (oui)
|
||||
:Capture d'image;
|
||||
:Lecture des données environnementales;
|
||||
:Sauvegarde en local;
|
||||
:Décrémenter le nombre d'images restantes;
|
||||
if (Toutes images capturées?) then (oui)
|
||||
:Désactivation de la configuration;
|
||||
stop
|
||||
else (non)
|
||||
:Envoi de l'intervalle au microcontrôleur;
|
||||
:Attente du prochain cycle;
|
||||
endif
|
||||
else (non)
|
||||
:Désactivation de la configuration;
|
||||
stop
|
||||
endif
|
||||
else (non)
|
||||
:Aucune configuration active;
|
||||
stop
|
||||
endif
|
||||
endif
|
||||
|
||||
stop
|
||||
|
||||
@enduml
|
||||
91
diagrams/raspi/03_structure_classes.puml
Normal file
91
diagrams/raspi/03_structure_classes.puml
Normal file
@@ -0,0 +1,91 @@
|
||||
@startuml Structure des Classes et Composants
|
||||
|
||||
skinparam {
|
||||
BackgroundColor white
|
||||
ClassBackgroundColor lightcyan
|
||||
ClassBorderColor gray
|
||||
ClassFontName Arial
|
||||
ClassFontSize 12
|
||||
}
|
||||
|
||||
class Config {
|
||||
+ BASE_DIR : string
|
||||
+ CONFIG_DIR : string
|
||||
+ PROJECT_DIR : string
|
||||
+ LOG_FILE : string
|
||||
+ CONFIG_FILE : string
|
||||
+ API_BASE_URL : string
|
||||
+ API_ENDPOINTS : dict
|
||||
+ DEFAULT_CONFIG : dict
|
||||
--
|
||||
+ ensure_directories()
|
||||
+ setup_logging()
|
||||
+ load_config()
|
||||
+ save_config()
|
||||
+ update_config(new_config)
|
||||
+ get(key, default)
|
||||
+ set(key, value)
|
||||
+ delete_config_file()
|
||||
+ decrement_remaining_images()
|
||||
}
|
||||
|
||||
class APIClient {
|
||||
- base_url : string
|
||||
- headers : dict
|
||||
--
|
||||
+ get_camera_status()
|
||||
+ upload_measurement(image_path, timestamp, temperature, humidity)
|
||||
+ confirm_stop()
|
||||
+ update_camera_config(status)
|
||||
+ check_connection()
|
||||
}
|
||||
|
||||
class TimelapseCaptureManager {
|
||||
- offline_dir : string
|
||||
--
|
||||
+ single_capture(online)
|
||||
+ run_capture_sequence(online)
|
||||
+ sync_offline_captures()
|
||||
+ count_offline_captures()
|
||||
- _move_to_offline(image_path, json_path)
|
||||
- _cleanup_local_capture(image_path, json_path)
|
||||
}
|
||||
|
||||
class "timelapse_online.py" as TimelapseOnline {
|
||||
+ main()
|
||||
}
|
||||
|
||||
class "timelapse_offline.py" as TimelapseOffline {
|
||||
+ main()
|
||||
}
|
||||
|
||||
package "sensors" {
|
||||
class EnvironmentalSensor {
|
||||
+ read_data()
|
||||
}
|
||||
|
||||
class Camera {
|
||||
+ capture_image()
|
||||
}
|
||||
|
||||
class MicroController {
|
||||
+ send_interval(interval)
|
||||
}
|
||||
}
|
||||
|
||||
Config "1" <-- "1" TimelapseOnline : utilise
|
||||
Config "1" <-- "1" TimelapseOffline : utilise
|
||||
Config "1" <-- "1" TimelapseCaptureManager : utilise
|
||||
APIClient "1" <-- "1" TimelapseOnline : utilise
|
||||
TimelapseCaptureManager "1" <-- "1" TimelapseOnline : utilise
|
||||
TimelapseCaptureManager "1" <-- "1" TimelapseOffline : utilise
|
||||
TimelapseCaptureManager "1" --> "1" EnvironmentalSensor : utilise
|
||||
TimelapseCaptureManager "1" --> "1" Camera : utilise
|
||||
APIClient "1" --> "1" Config : utilise
|
||||
TimelapseOffline ..> MicroController : utilise
|
||||
|
||||
note bottom of Config : "Gestion de la configuration\nlocale et persistance"
|
||||
note bottom of APIClient : "Communication avec\nle serveur distant"
|
||||
note bottom of TimelapseCaptureManager : "Orchestration du processus\nde capture d'images"
|
||||
|
||||
@enduml
|
||||
78
diagrams/raspi/04_sequence_synchronisation.puml
Normal file
78
diagrams/raspi/04_sequence_synchronisation.puml
Normal file
@@ -0,0 +1,78 @@
|
||||
@startuml Séquence de Synchronisation des Données
|
||||
|
||||
skinparam {
|
||||
BackgroundColor white
|
||||
SequenceGroupBorderColor gray
|
||||
SequenceGroupBodyBackgroundColor whitesmoke
|
||||
ParticipantBackgroundColor lightblue
|
||||
ParticipantBorderColor gray
|
||||
LifeLineBorderColor gray
|
||||
ArrowColor #666666
|
||||
}
|
||||
|
||||
actor "Système" as System
|
||||
participant "sync_offline_data.py" as Sync
|
||||
participant "APIClient" as API
|
||||
participant "TimelapseCaptureManager" as Manager
|
||||
participant "Config" as Config
|
||||
database "Stockage local" as Storage
|
||||
database "Serveur API" as Server
|
||||
|
||||
System -> Sync : Exécution du script
|
||||
activate Sync
|
||||
|
||||
Sync -> API : check_connection()
|
||||
activate API
|
||||
API --> Sync : Connexion disponible
|
||||
deactivate API
|
||||
|
||||
Sync -> Manager : count_offline_captures()
|
||||
activate Manager
|
||||
Manager -> Storage : Listing des dossiers offline
|
||||
Storage --> Manager : Liste des captures
|
||||
Manager --> Sync : Nombre de captures hors ligne
|
||||
deactivate Manager
|
||||
|
||||
alt Captures hors ligne disponibles
|
||||
Sync -> Manager : sync_offline_captures()
|
||||
activate Manager
|
||||
|
||||
loop Pour chaque capture hors ligne
|
||||
Manager -> Storage : Lire données JSON
|
||||
activate Storage
|
||||
Storage --> Manager : Données (timestamp, température, etc.)
|
||||
deactivate Storage
|
||||
|
||||
Manager -> Storage : Lire image
|
||||
activate Storage
|
||||
Storage --> Manager : Fichier image
|
||||
deactivate Storage
|
||||
|
||||
Manager -> API : upload_measurement()
|
||||
activate API
|
||||
API -> Server : POST /camera/upload
|
||||
|
||||
alt Upload réussi
|
||||
Server --> API : Confirmation (ID image)
|
||||
API --> Manager : Succès
|
||||
Manager -> Storage : Suppression des fichiers locaux
|
||||
Manager -> Config : Mise à jour du statut
|
||||
else Échec de l'upload
|
||||
Server --> API : Erreur
|
||||
API --> Manager : Échec
|
||||
note right: Conservation des fichiers locaux\npour tentative ultérieure
|
||||
end
|
||||
|
||||
deactivate API
|
||||
end
|
||||
|
||||
Manager --> Sync : Nombre de captures synchronisées
|
||||
deactivate Manager
|
||||
else Aucune capture à synchroniser
|
||||
Sync -> Sync : Fin sans action
|
||||
end
|
||||
|
||||
Sync --> System : Rapport de synchronisation
|
||||
deactivate Sync
|
||||
|
||||
@enduml
|
||||
69
diagrams/raspi/05_deploiement_infrastructure.puml
Normal file
69
diagrams/raspi/05_deploiement_infrastructure.puml
Normal file
@@ -0,0 +1,69 @@
|
||||
@startuml infra_raspi
|
||||
|
||||
skinparam {
|
||||
BackgroundColor white
|
||||
NodeBackgroundColor lightyellow
|
||||
NodeBorderColor gray
|
||||
AgentBackgroundColor lightcyan
|
||||
AgentBorderColor gray
|
||||
ArrowColor #666666
|
||||
ComponentBackgroundColor lightblue
|
||||
ComponentBorderColor gray
|
||||
}
|
||||
|
||||
artifact "Raspbian OS" as linux
|
||||
|
||||
node "Raspberry Pi" as raspi {
|
||||
agent "Service Systemd" as service
|
||||
artifact "timelapse.service" as timelapseService
|
||||
artifact "script.sh" as script
|
||||
|
||||
service --> timelapseService : gère
|
||||
service --> script : exécute
|
||||
|
||||
component "Scripts Python" as scripts {
|
||||
artifact "timelapse_online.py" as pyOnline
|
||||
artifact "timelapse_offline.py" as pyOffline
|
||||
artifact "sync_offline_data.py" as pySync
|
||||
}
|
||||
|
||||
component "Modules Timelapse" as modules {
|
||||
artifact "config.py" as config
|
||||
artifact "api_client.py" as apiClient
|
||||
artifact "capture.py" as capture
|
||||
artifact "sensors.py" as sensors
|
||||
}
|
||||
|
||||
artifact "Caméra Pi" as cam
|
||||
artifact "Microcontrôleur" as micro
|
||||
}
|
||||
|
||||
cloud "Internet" as internet {
|
||||
node "Serveur API" as api_server {
|
||||
database "Base de données" as db
|
||||
folder "Stockage d'images" as images
|
||||
}
|
||||
}
|
||||
|
||||
linux --> service : exécute
|
||||
service --> script : lance
|
||||
script --> scripts : appelle selon\nétat connexion
|
||||
scripts --> modules : utilisent
|
||||
modules --> cam : contrôle
|
||||
modules --> micro : communique
|
||||
modules --> internet : envoie données
|
||||
internet --> modules : récupère configuration
|
||||
|
||||
note right of service : "Démarrage au boot\net exécution périodique"
|
||||
note right of scripts : "Sélection auto du mode\nselon connectivité"
|
||||
note bottom of cam : "Capture des images\ndu timelapse"
|
||||
note bottom of micro : "Gestion de l'intervalle\nde capture"
|
||||
|
||||
legend right
|
||||
<b>Infrastructure de Déploiement Timelapse</b>
|
||||
Ce diagramme représente l'infrastructure complète
|
||||
du système timelapse, depuis le service systemd
|
||||
jusqu'à la communication avec le serveur distant.
|
||||
endlegend
|
||||
|
||||
@enduml
|
||||
Reference in New Issue
Block a user