543 lines
19 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@startuml WalkGuide_Component_Diagram
title Component Diagram — WalkGuide System (v2.0)
skinparam componentStyle rectangle
skinparam backgroundColor #FAFAFA
skinparam component {
BackgroundColor #EEF2FF
BorderColor #6366F1
FontColor #1E1B4B
FontSize 11
}
skinparam package {
BackgroundColor #F0F4FF
BorderColor #818CF8
FontColor #1E1B4B
FontSize 12
FontStyle bold
}
skinparam interface {
BackgroundColor #DBEAFE
BorderColor #3B82F6
}
skinparam database {
BackgroundColor #FEF3C7
BorderColor #D97706
}
skinparam cloud {
BackgroundColor #F0FDF4
BorderColor #16A34A
}
skinparam arrow {
Color #4B5563
FontSize 9
FontColor #374151
}
skinparam note {
BackgroundColor #FFFBEB
BorderColor #F59E0B
FontSize 9
}
' ─────────────────────────────────────────────
' MOBILE DEVICE — Flutter App
' ─────────────────────────────────────────────
package "Mobile Device (Flutter App)" as FLUTTER #E8EAF6 {
package "Presentation Layer" as PRESENTATION {
[ServerConnectScreen] as SCS
[SplashScreen] as SS
[LoginScreen] as LS
[RegisterScreen] as RS
package "User Screens" as US_SCREENS {
[WalkGuideScreen] as WGS
[SosScreen] as SOSS
[ActivityLogScreen] as ALS
[NotificationScreen] as NS
[NavigationModeScreen] as NMS
[UserSettingsScreen] as USS
[CallScreen] as CS
[ManualScreen] as MS
[UserPairingScreen] as UPS
}
package "Guardian Screens" as GS_SCREENS {
[GuardianDashboardScreen] as GDS
[GuardianMapScreen] as GMS
[GuardianActivityLogScreen] as GALS
[GuardianSendNotifScreen] as GSNS
[GuardianAiConfigScreen] as GACS
[GuardianVoiceCmdScreen] as GVCS
[GuardianShortcutScreen] as GSHS
[GuardianGeofenceScreen] as GGFS
[GuardianPairingScreen] as GPS
[IncomingCallScreen] as ICS
}
}
package "Application Layer (BLoC / Cubit)" as BLOC_LAYER {
[AuthBloc] as AuthBloc
[PairingBloc] as PairingBloc
[WalkGuideBloc] as WGBloc
[SosBloc] as SosBloc
[LocationBloc] as LocBloc
[NotificationBloc] as NotifBloc
[ActivityLogBloc] as ActLogBloc
[VoiceCommandBloc] as VCBloc
[ServerConnectBloc] as SCBloc
[CallBloc] as CallBloc
[GuardianDashboardBloc] as GDBloc
}
package "Domain Layer" as DOMAIN {
package "Use Cases" as USECASES {
[LoginUseCase] as LoginUC
[RegisterUseCase] as RegUC
[LogoutUseCase] as LogoutUC
[InviteUserUseCase] as InviteUC
[RespondPairingUseCase] as RespUC
[UnpairUseCase] as UnpairUC
[StartSessionUseCase] as StartUC
[StopSessionUseCase] as StopUC
[LogObstacleUseCase] as LogObsUC
[TriggerSosUseCase] as TrigSosUC
[UpdateLocationUseCase] as UpdLocUC
}
package "Repository Interfaces" as REPO_INTF {
interface "IAuthRepository" as IAuthRepo
interface "IPairingRepository" as IPairRepo
interface "IWalkGuideRepository" as IWGRepo
interface "IActivityLogRepository" as IActRepo
interface "ISosRepository" as ISosRepo
interface "ILocationRepository" as ILocRepo
interface "INotificationRepository" as INotifRepo
interface "IAiConfigRepository" as IAIRepo
}
}
package "Data Layer" as DATA {
package "Repository Implementations" as REPO_IMPL {
[AuthRepositoryImpl] as AuthRepoImpl
[PairingRepositoryImpl] as PairRepoImpl
[WalkGuideRepositoryImpl] as WGRepoImpl
[ActivityLogRepositoryImpl] as ActRepoImpl
[SosRepositoryImpl] as SosRepoImpl
[LocationRepositoryImpl] as LocRepoImpl
[NotificationRepositoryImpl] as NotifRepoImpl
[AiConfigRepositoryImpl] as AIRepoImpl
}
package "Remote Data Sources" as REMOTE_DS {
[AuthRemoteDataSource] as AuthDS
[WalkGuideRemoteDataSource] as WGDS
[ActivityLogRemoteDataSource] as ActDS
[SosRemoteDataSource] as SosDS
[LocationRemoteDataSource] as LocDS
[NotificationRemoteDataSource] as NotifDS
[GuardianRemoteDataSource] as GrdDS
}
package "Local Data Sources (Drift/SQLite)" as LOCAL_DS {
[SecureStorageService] as SecStore
[LocalDatabase (Drift)] as DriftDB
[SharedPreferencesService] as SharedPref
}
package "Core Services (Singletons)" as CORE_SVC {
[TtsService\n(flutter_tts)] as TTS
[SttService\n(speech_to_text)] as STT
[VoiceCommandHandler] as VCH
[HapticService\n(vibration)] as HAP
[HardwareShortcutListener] as HSL
[FcmService\n(firebase_messaging)] as FCMSvc
[WebSocketService\n(stomp_dart_client)] as WSSvc
[AgoraService\n(agora_rtc_engine)] as AgoraSvc
}
package "AI Engine (On-Device)" as AI_ENGINE {
[ModelLoader\n(tflite_flutter)] as ModelLoader
[YoloDetector\n(YOLOv8n)] as YOLO
[ObstacleAnalyzer] as ObsAnalyzer
}
[ApiClient\n(Dio + Interceptors)] as DioClient
}
}
' ─────────────────────────────────────────────
' BACKEND SERVER — Spring Boot
' ─────────────────────────────────────────────
package "Backend Server (Spring Boot @ 202.46.28.160:8080)" as BACKEND #E8F5E9 {
package "Security & Config" as SEC_CFG {
[SecurityConfig\n(CORS, CSRF, RBAC)] as SecConfig
[JwtAuthFilter\n(OncePerRequestFilter)] as JWTFilter
[JwtUtil\n(JJWT)] as JWTUtil
[CustomUserDetailsService] as CUDS
[WebSocketConfig\n(STOMP)] as WSConfig
[GlobalExceptionHandler\n(@ControllerAdvice)] as GEH
[SwaggerConfig\n(Springdoc OpenAPI)] as SwagConfig
}
package "Controller Layer" as CTRL {
[AuthController\n/api/v1/auth] as AuthCtrl
[PairingController\n/api/v1/shared/pairing] as PairCtrl
[GuardianController\n/api/v1/guardian] as GrdCtrl
[UserController\n/api/v1/user] as UserCtrl
[CallController\n/api/v1/shared/call] as CallCtrl
}
package "Service Layer" as SVC {
[AuthService] as AuthSvc
[PairingService] as PairSvc
[ActivityLogService] as ActLogSvc
[LocationService\n(+ Haversine)] as LocSvc
[ObstacleLogService] as ObsLogSvc
[NotificationService] as NotifSvc
[SosService] as SosSvc
[AiConfigService] as AICfgSvc
[VoiceCommandService] as VCSvc
[HardwareShortcutService] as HWSvc
[GeofenceService\n(Haversine)] as GeoSvc
[UserSettingsService] as UserSetSvc
[FcmService\n(Firebase Admin)] as FcmBackSvc
[AgoraTokenService] as AgoraSvcBE
[GuardianDashboardService] as GDSvc
}
package "WebSocket Broadcaster" as WS_BROADCAST {
[LocationBroadcaster\n(SimpMessagingTemplate)] as LocBcast
}
package "Repository Layer (Spring Data JPA)" as REPO {
[UserRepository] as UserRepo
[PairingRelationRepository] as PairRepo
[ActivityLogRepository] as ActRepo
[ObstacleLogRepository] as ObsRepo
[LocationHistoryRepository] as LocRepo
[GuardianNotificationRepository] as NotifRepo
[SosEventRepository] as SosRepo
[UserSettingsRepository] as UserSetRepo
[AiConfigRepository] as AIRepo
[VoiceCommandConfigRepository] as VCRepo
[HardwareShortcutRepository] as HWRepo
[GeofenceConfigRepository] as GeoRepo
[RefreshTokenRepository] as RTRepo
}
package "Domain / Entity" as ENTITY {
[User] as UEnt
[PairingRelation] as PRel
[ActivityLog] as ActEnt
[ObstacleLog] as ObsEnt
[LocationHistory] as LocEnt
[GuardianNotification] as NotifEnt
[SosEvent] as SosEnt
[UserSettings] as UserSetEnt
[AiConfig] as AICfgEnt
[VoiceCommandConfig] as VCEnt
[HardwareShortcut] as HWEnt
[GeofenceConfig] as GeoEnt
[RefreshToken] as RTEnt
}
}
' ─────────────────────────────────────────────
' EXTERNAL SERVICES
' ─────────────────────────────────────────────
package "External Services" as EXTERNAL #FFF8E1 {
cloud "Firebase (FCM)\nPush Notifications" as FCM
cloud "Agora RTC\nVoIP Audio Call" as AGORA
cloud "OpenStreetMap\n(flutter_map tiles)" as OSM
}
database "PostgreSQL\n202.46.28.160:2002\n(University Server)\nFlyway Migrations V1-V16" as PGDB
' ─────────────────────────────────────────────
' PRESENTATION → BLOC
' ─────────────────────────────────────────────
SCS --> SCBloc
SS --> AuthBloc
LS --> AuthBloc
RS --> AuthBloc
WGS --> WGBloc
WGS --> VCBloc
SOSS --> SosBloc
ALS --> ActLogBloc
NS --> NotifBloc
NMS --> LocBloc
USS --> AuthBloc
CS --> CallBloc
UPS --> PairingBloc
GDS --> GDBloc
GMS --> LocBloc
GALS --> ActLogBloc
GSNS --> NotifBloc
GACS --> AIRepoImpl
GVCS --> VCBloc
GSHS --> VCBloc
GGFS --> GDBloc
GPS --> PairingBloc
ICS --> CallBloc
' ─────────────────────────────────────────────
' BLOC → USE CASES
' ─────────────────────────────────────────────
AuthBloc --> LoginUC
AuthBloc --> RegUC
AuthBloc --> LogoutUC
PairingBloc --> InviteUC
PairingBloc --> RespUC
PairingBloc --> UnpairUC
WGBloc --> StartUC
WGBloc --> StopUC
WGBloc --> LogObsUC
SosBloc --> TrigSosUC
LocBloc --> UpdLocUC
CallBloc --> AgoraSvc
VCBloc --> VCH
' ─────────────────────────────────────────────
' USE CASES → REPOSITORY INTERFACES
' ─────────────────────────────────────────────
LoginUC --> IAuthRepo
RegUC --> IAuthRepo
LogoutUC --> IAuthRepo
InviteUC --> IPairRepo
RespUC --> IPairRepo
UnpairUC --> IPairRepo
StartUC --> IWGRepo
StopUC --> IWGRepo
LogObsUC --> IWGRepo
TrigSosUC --> ISosRepo
UpdLocUC --> ILocRepo
' ─────────────────────────────────────────────
' INTERFACES → IMPLEMENTATIONS
' ─────────────────────────────────────────────
IAuthRepo <|.. AuthRepoImpl
IPairRepo <|.. PairRepoImpl
IWGRepo <|.. WGRepoImpl
IActRepo <|.. ActRepoImpl
ISosRepo <|.. SosRepoImpl
ILocRepo <|.. LocRepoImpl
INotifRepo <|.. NotifRepoImpl
IAIRepo <|.. AIRepoImpl
' ─────────────────────────────────────────────
' REPO IMPL → DATA SOURCES
' ─────────────────────────────────────────────
AuthRepoImpl --> AuthDS
AuthRepoImpl --> SecStore
PairRepoImpl --> GrdDS
WGRepoImpl --> WGDS
WGRepoImpl --> DriftDB
ActRepoImpl --> ActDS
SosRepoImpl --> SosDS
LocRepoImpl --> LocDS
NotifRepoImpl --> NotifDS
NotifRepoImpl --> DriftDB
AIRepoImpl --> GrdDS
' ─────────────────────────────────────────────
' REMOTE DATA SOURCES → DioClient
' ─────────────────────────────────────────────
AuthDS --> DioClient
WGDS --> DioClient
ActDS --> DioClient
SosDS --> DioClient
LocDS --> DioClient
NotifDS --> DioClient
GrdDS --> DioClient
' ─────────────────────────────────────────────
' CORE SERVICES INTERCONNECT
' ─────────────────────────────────────────────
WGBloc --> YOLO
WGBloc --> TTS
WGBloc --> HAP
YOLO --> ModelLoader
YOLO --> ObsAnalyzer
ObsAnalyzer --> TTS
ObsAnalyzer --> HAP
VCH --> STT
VCH --> DriftDB
HSL --> DriftDB
FCMSvc --> DriftDB
SharedPref --> DioClient : baseUrl
' ─────────────────────────────────────────────
' DioClient → Backend REST API
' ─────────────────────────────────────────────
DioClient -down-> AuthCtrl : "POST /api/v1/auth/register\nPOST /api/v1/auth/login\nPOST /api/v1/auth/refresh\nPOST /api/v1/auth/logout\nPUT /api/v1/auth/fcm-token\nGET /api/v1/auth/ping"
DioClient -down-> PairCtrl : "POST /shared/pairing/invite\nPOST /shared/pairing/respond\nDELETE /shared/pairing/unpair\nGET /shared/pairing/status"
DioClient -down-> UserCtrl : "GET /user/profile\nPOST /user/location\nPOST /user/obstacle\nPOST /user/sos\nGET /user/notifications\nPOST /user/walkguide/start\nPOST /user/walkguide/stop"
DioClient -down-> GrdCtrl : "GET /guardian/dashboard\nGET /guardian/user-location\nPOST /guardian/notifications/send\nPUT /guardian/ai-config\nPUT /guardian/geofence"
DioClient -down-> CallCtrl : "POST /shared/call/token\nPOST /shared/call/notify"
' WebSocket STOMP
WSSvc -down-> WSConfig : "ws://host:8080/ws\n(STOMP)\n/topic/location/{userId}\n/queue/sos/{guardianId}\n/queue/notif/{userId}"
' ─────────────────────────────────────────────
' BACKEND SECURITY FLOW
' ─────────────────────────────────────────────
JWTFilter --> JWTUtil : validate token
JWTFilter --> CUDS : load user
JWTFilter -up-> SecConfig : filter chain
SecConfig -right-> JWTFilter
' ─────────────────────────────────────────────
' CONTROLLERS → SERVICES
' ─────────────────────────────────────────────
AuthCtrl --> AuthSvc
PairCtrl --> PairSvc
GrdCtrl --> GDSvc
GrdCtrl --> LocSvc
GrdCtrl --> ActLogSvc
GrdCtrl --> ObsLogSvc
GrdCtrl --> NotifSvc
GrdCtrl --> SosSvc
GrdCtrl --> AICfgSvc
GrdCtrl --> VCSvc
GrdCtrl --> HWSvc
GrdCtrl --> GeoSvc
UserCtrl --> AuthSvc
UserCtrl --> LocSvc
UserCtrl --> ObsLogSvc
UserCtrl --> SosSvc
UserCtrl --> ActLogSvc
UserCtrl --> NotifSvc
UserCtrl --> UserSetSvc
UserCtrl --> VCSvc
UserCtrl --> HWSvc
UserCtrl --> AICfgSvc
CallCtrl --> AgoraSvcBE
' ─────────────────────────────────────────────
' SERVICES CROSS-DEPENDENCIES
' ─────────────────────────────────────────────
AuthSvc --> PairSvc : seed defaults on register
PairSvc --> VCSvc : seedDefaults()
PairSvc --> HWSvc : seedDefaults()
PairSvc --> AICfgSvc : create config on pair
PairSvc --> FcmBackSvc : send FCM invite/response
NotifSvc --> FcmBackSvc : send FCM notification
SosSvc --> FcmBackSvc : send FCM SOS high-priority
AICfgSvc --> FcmBackSvc : notify settings updated
LocSvc --> GeoSvc : checkGeofence()
LocSvc --> LocBcast : broadcastLocation()
LocSvc --> ActLogSvc : log LOCATION_UPDATE
NotifSvc --> LocBcast : broadcastNotification()
SosSvc --> LocBcast : broadcastSos()
SosSvc --> ActLogSvc : log SOS_TRIGGERED
ActLogSvc --> LocBcast : broadcast to Guardian
GDSvc --> LocSvc
GDSvc --> ActLogSvc
GDSvc --> NotifSvc
GDSvc --> SosSvc
' ─────────────────────────────────────────────
' SERVICES → REPOSITORIES
' ─────────────────────────────────────────────
AuthSvc --> UserRepo
AuthSvc --> RTRepo
AuthSvc --> ActLogSvc
PairSvc --> PairRepo
PairSvc --> UserRepo
ActLogSvc --> ActRepo
LocSvc --> LocRepo
LocSvc --> PairRepo
ObsLogSvc --> ObsRepo
ObsLogSvc --> ActLogSvc
NotifSvc --> NotifRepo
NotifSvc --> PairRepo
SosSvc --> SosRepo
SosSvc --> PairRepo
AICfgSvc --> AIRepo
VCSvc --> VCRepo
HWSvc --> HWRepo
GeoSvc --> GeoRepo
UserSetSvc --> UserSetRepo
FcmBackSvc --> UserRepo
AgoraSvcBE --> UserRepo
' ─────────────────────────────────────────────
' REPOSITORIES → ENTITIES (JPA/Hibernate)
' ─────────────────────────────────────────────
UserRepo --> UEnt
PairRepo --> PRel
ActRepo --> ActEnt
ObsRepo --> ObsEnt
LocRepo --> LocEnt
NotifRepo --> NotifEnt
SosRepo --> SosEnt
UserSetRepo --> UserSetEnt
AIRepo --> AICfgEnt
VCRepo --> VCEnt
HWRepo --> HWEnt
GeoRepo --> GeoEnt
RTRepo --> RTEnt
' ─────────────────────────────────────────────
' ENTITIES → DATABASE
' ─────────────────────────────────────────────
UEnt --> PGDB : JPA/Hibernate
PRel --> PGDB
ActEnt --> PGDB
ObsEnt --> PGDB
LocEnt --> PGDB
NotifEnt --> PGDB
SosEnt --> PGDB
UserSetEnt --> PGDB
AICfgEnt --> PGDB
VCEnt --> PGDB
HWEnt --> PGDB
GeoEnt --> PGDB
RTEnt --> PGDB
' ─────────────────────────────────────────────
' EXTERNAL SERVICES
' ─────────────────────────────────────────────
FcmBackSvc -right-> FCM : "Firebase Admin SDK\nFirebaseMessaging.send()"
AgoraSvcBE -right-> AGORA : "Generate RTC Token\n(server-side Agora SDK)"
AgoraSvc --> AGORA : "agora_rtc_engine\nJoin Channel (audio-only)"
FCMSvc --> FCM : "firebase_messaging\nReceive push"
GMS --> OSM : "flutter_map\nOpenStreetMap tiles"
note top of PGDB
Tables (Flyway V1V16):
users, pairing_relations,
activity_logs, obstacle_logs,
location_history, guardian_notifications,
sos_events, user_settings, ai_configs,
voice_command_configs, hardware_shortcuts,
geofence_configs, refresh_tokens
end note
note right of AI_ENGINE
On-Device AI (No server call):
YOLOv8n .tflite (640×640)
→ detect obstacles
→ direction: LEFT/CENTER/RIGHT
→ TTS + Haptic alert
NNAPI delegate (Android AI accel.)
end note
note left of SharedPref
Dynamic Server URL:
User inputs "http://202.46.28.160:8080"
Saved to SharedPreferences
No hardcoded BASE_URL in APK
end note
note bottom of WSSvc
WebSocket STOMP:
/topic/location/{userId} → Guardian map real-time
/queue/sos/{guardianId} → SOS alert instant
/queue/notif/{userId} → Notification push
end note
@enduml