Files
sides/.planning/codebase/INTEGRATIONS.md

156 lines
6.9 KiB
Markdown

# External Integrations
**Analysis Date:** 2026-05-20
## External Services
### Firebase Cloud Messaging (FCM)
- **Purpose:** Push notifications to mobile/web clients when sensor thresholds are triggered
- **SDK/Client:** `google/auth` ^1.49 (Google Auth for OAuth2 token generation)
- **Implementation:** `src/app/Services/FcmService.php`
- Authenticates via Service Account Credentials (`FIREBASE_CREDENTIALS` env → JSON file)
- Sends topic-based notifications to `FCM_TOPIC_RAINFALL_WARNING`
- Calls FCM HTTP v1 API: `https://fcm.googleapis.com/v1/projects/{projectId}/messages:send`
- **Triggered by:** `src/app/Http/Controllers/Api/AlertController.php` (API endpoint `POST /api/alert`)
- **Auth env vars:** `FIREBASE_PROJECT_ID`, `FIREBASE_CREDENTIALS`, `FCM_TOPIC_RAINFALL_WARNING`
### FTP Server (myvscada.com)
- **Purpose:** Retrieving raw sensor data files (CSV) from remote SCADA FTP server
- **Implementation:** `autoscript/sidesdecode.py`
- FTP server: `myvscada.com`, credentials hardcoded in script
- Folder structure: `files/SIDES/SUCCESS/{year}/{month}/{day}/`
- Error folder: `files/SIDES/ERROR/`
- Processes CSV files containing rainfall, water level, siren, and battery data
### SIDES API (Internal Callback)
- **Purpose:** Alert notification trigger from ETL script to Laravel API
- **Implementation:** `autoscript/sidesdecode.py``send_alert_to_laravel()`
- Posts to `https://sides.tck.com.my/api/alert`
- Payload: `{ stationid, level, stationtype }`
- Received by: `src/app/Http/Controllers/Api/AlertController.php`
## Third-Party Libraries
### Google Auth (`google/auth` ^1.49)
- **Connects to:** Google OAuth2 for Firebase service account authentication
- **Used in:** `src/app/Services/FcmService.php`
- **Purpose:** Generates access tokens for FCM HTTP v1 API calls
### Laravel DomPDF (`barryvdh/laravel-dompdf` ^3.1)
- **Connects to:** N/A (local PDF generation)
- **Used in:** Siren and notification history PDF exports
- **Purpose:** Generates downloadable PDF reports from Blade templates
### Maatwebsite Excel (`maatwebsite/excel` ^3.1)
- **Connects to:** N/A (local Excel generation)
- **Used in:** `src/app/Exports/HourlyRainfallExport.php`, `src/app/Exports/WaterLevelExport.php`
- **Purpose:** Export historical rainfall and water level data to Excel (.xlsx)
### psycopg2 (Python)
- **Connects to:** PostgreSQL database directly (bypasses Laravel)
- **Used in:** `autoscript/sidesdecode.py`
- **Purpose:** Direct database insertion of sensor data from decoded CSV files
## Internal Services
### API Routes (REST)
- **Base path:** `/api/`
- **Defined in:** `src/routes/api.php`
- **Endpoints:**
- `GET /api/station/current` — Current station data (rainfall, water level, siren)
- `GET /api/station/rainfall` — Rainfall-specific data
- `GET /api/station/waterlevel` — Water level-specific data
- `GET /api/station/notification` — Current day notifications
- `GET /api/station/history` — 3-day notification history
- `GET /api/station/siren` — Latest siren status
- `GET /api/station/siren/history` — 3-day siren history
- `POST /api/login` — Mobile/API authentication
- `POST /api/alert` — Trigger FCM push notification
### Python ETL Script
- **Location:** `autoscript/sidesdecode.py`
- **Flow:** FTP download → CSV decode → PostgreSQL insert → API alert trigger
- **Data types:** Rainfall, water level, siren status, battery levels
- **Threshold logic:** Rainfall hourly ≥30mm (Warning), ≥60mm (Danger); Water level alert/warning/danger from CSV config
- **Logs:** `autoscript/sidesdecode.log`, `autoscript/sidesdecode_error.log`
## Authentication Providers
### Web Authentication (Session-based)
- **Provider:** Laravel Breeze (`laravel/breeze ^2.3`)
- **Guard:** Session-based (`web` guard, `session` driver)
- **User model:** `App\Models\User` (`src/app/Models/User.php`)
- **Features:** Login, registration, email verification, password reset, password confirmation
- **Role system:** `access_level` field on users table (1 = admin, 0 = regular)
- **Account security:** `is_blocked` and `login_attempts` fields on users table
- **Implementation:** `src/routes/auth.php`, `src/app/Http/Controllers/Auth/`
### API Authentication
- **Provider:** Custom token-based (via `POST /api/login`)
- **Implementation:** `src/app/Http/Controllers/Api/AuthController.php`
- **Used by:** Mobile client or external data consumers
### Password Reset
- **Custom notification:** `src/app/Notifications/ResetPasswordNotification.php`
- **Channel:** Email (SMTP)
- **Branded:** "SIDES - Password Reset" subject line
## Payment / Billing
Not applicable — This is an environmental monitoring dashboard, no payment integration.
## Email / Notifications
### Email
- **Default mailer:** `log` (writes to Laravel log, not actually sent in current config) — `src/config/mail.php`
- **Configured transports:** SMTP, SES, Postmark, Resend, Sendmail, Log, Array
- **Env vars:** `MAIL_MAILER`, `MAIL_HOST`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`
- **From address:** Configurable via `MAIL_FROM_ADDRESS` and `MAIL_FROM_NAME`
### Push Notifications
- **Firebase Cloud Messaging (FCM)** — Topic-based push notifications
- **Implementation:** `src/app/Services/FcmService.php`
- **Trigger:** Sensor threshold breaches detected by `autoscript/sidesdecode.py`
### In-App Notifications
- **Notification views:** `src/resources/views/` — rainfall, water level, siren notification pages
- **Data source:** `notification` table in PostgreSQL
## File Storage
### Primary Storage
- **Default disk:** `local``src/storage/app/private/` (`src/config/filesystems.php`)
- **Public disk:** `src/storage/app/public/` — symlinked to `public/storage`
- **No cloud storage configured** — S3 config present but not active
### FTP File Management
- **FTP server:** `myvscada.com` — remote sensor data storage
- **File lifecycle:** SUCCESS folder → processed → optional move to SUCCESS/ERROR subfolders
## Queue / Background Jobs
### Queue Configuration
- **Default driver:** `database` (`src/config/queue.php`)
- **Table:** `jobs` (database-backed queue)
- **Failed jobs:** `failed_jobs` table, driver `database-uuids`
- **Job batching:** `job_batches` table
- **Run command:** `php artisan queue:listen --tries=1` (via `composer dev`)
- **Available drivers:** sync, database, beanstalkd, SQS, redis (not actively used beyond database)
## Caching
### Cache Configuration
- **Default store:** `database` (`src/config/cache.php`)
- **Table:** `cache` (database-backed cache)
- **Available stores:** array, database, file, memcached, redis, dynamodb, octane, failover
- **Redis:** Configured but not actively used (`src/config/database.php` has Redis connection block)
- **Session driver:** `database` (sessions table)
## Search
No dedicated search engine integration (Elasticsearch, Algolia, etc.). All queries use direct PostgreSQL with raw SQL joins and subqueries.
---
*Integration audit: 2026-05-20*