Satelit & Layanan Eksternal
Copernicus CDSE, Google Earth Engine, PostGIS, dan abstraksi provider.
Memahami Setiap Layanan Eksternal
EUDR Forest Analyzer tidak menghasilkan data satelit sendiri. Sistem ini bergantung pada beberapa layanan eksternal untuk mengambil citra, mendeteksi deforestasi, mengklasifikasikan tutupan lahan, dan menyimpan hasil geospasial. Tutorial ini memperkenalkan setiap layanan tersebut.
Google Earth Engine
GEE adalah platform cloud dengan petabyte data satelit. Alih-alih mengunduh citra ke server Anda sendiri, Anda mengirim permintaan komputasi ke infrastruktur Google dan hanya menerima hasil yang dibutuhkan.
Aplikasi ini menggunakan empat dataset dari GEE:
lossyear menunjukkan tahun berapa pohon hilang (nilai 1–23 untuk 2001–2023).
Autentikasi dilakukan melalui file kunci service account. Backend memanggil ee.Initialize(credentials) saat startup, dan setiap panggilan GEE berikutnya menggunakan kembali sesi tersebut.
PostgreSQL + PostGIS
PostGIS mengubah database PostgreSQL biasa menjadi database spasial. Batas-batas plot disimpan sebagai kolom geometry, sehingga Anda dapat menjalankan kueri seperti “apakah poligon ini tumpang tindih dengan kawasan lindung?”
Aplikasi ini menggunakan connection pooling untuk menghindari biaya membuka koneksi baru setiap request:
_connection_pool = pool.ThreadedConnectionPool(
minconn=pool_size,
maxconn=pool_size + max_overflow,
host=os.getenv("DB_HOST", "localhost"),
database=os.getenv("DB_NAME", "eudr_forest_analyzer"),
cursor_factory=RealDictCursor
)
pool_size (default 5) koneksi setiap saat. Izinkan hingga pool_size + max_overflow (default 15) saat lalu lintas tinggi.row["plot_id"] alih-alih row[0].Abstraksi Provider
Codebase mendukung beberapa backend data satelit. Sebuah factory pattern di providers/factory.py menentukan mana yang digunakan berdasarkan satu variabel lingkungan:
def get_provider() -> DataProvider:
provider_type = os.getenv("DATA_PROVIDER", "gee")
if provider_type == "gee":
return GEEProvider()
elif provider_type == "planetary":
return PlanetaryComputerProvider()
elif provider_type == "cdse":
return CDSEProvider()
DATA_PROVIDER dari environment. Default-nya adalah "gee" (Google Earth Engine).DataProvider), sehingga sisa aplikasi tidak perlu tahu backend mana yang diajak berkomunikasi.Semua layanan analisis memanggil get_provider() dan menggunakan objek yang dikembalikan. Mereka tidak pernah mengimpor GEEProvider secara langsung.
Provider GEE: Cara Kerjanya di Balik Layar
Provider GEE (providers/gee_provider.py, 392 baris) adalah lapisan delegasi — ia tidak memproses data satelit secara langsung, melainkan mendelegasikan ke layanan-layanan khusus yang sudah ada di codebase.
lossyear.
Autentikasi dilakukan melalui service account key file. Saat startup, provider memanggil ee.Initialize(credentials) menggunakan kredensial dari variabel lingkungan GEE_SERVICE_ACCOUNT_KEY_FILE.
Dengan hanya 392 baris, provider GEE sengaja dibuat tipis. Seluruh kompleksitas pemrosesan data satelit berada di layanan-layanan khusus (glad_alert_service, radd_alert_service, land_cover_service, sentinel_imagery_service). Provider hanya berfungsi sebagai jembatan antara antarmuka DataProvider dan layanan-layanan tersebut.
Provider CDSE: Sistem Produksi yang Aktif
Provider CDSE (providers/cdse_provider.py, 1.920 baris) adalah provider paling komprehensif dan merupakan yang digunakan saat ini di produksi (DATA_PROVIDER=cdse).
File ini berisi tiga kelas helper utama:
data-api.globalforestwatch.org.
services.terrascope.be/wms), lalu STAC (services.terrascope.be/stac) jika WMS gagal.
identity.dataspace.copernicus.eu dan mengambil citra satelit melalui SentinelHub Process API (sh.dataspace.copernicus.eu).
Provider ini berkomunikasi dengan lima endpoint API eksternal:
Saat GFW API tidak tersedia (timeout, error, atau tidak ada koneksi), provider CDSE tidak gagal total. Sebagai gantinya, ia menghasilkan data simulasi deterministik menggunakan hash MD5 dari geometri sebagai seed. Ini berarti geometri yang sama selalu menghasilkan data simulasi yang sama — konsisten untuk pengujian dan demonstrasi.
Layanan Email SMTP
Sistem mengirim email pada momen-momen penting: aktivasi akun, notifikasi analisis selesai, ringkasan batch dengan lampiran PDF, dan peringatan kegagalan. Layanan email menggunakan SMTP (biasanya Gmail) dengan template HTML yang disesuaikan dengan branding aplikasi.
Metode utama meliputi send_activation_email(), send_analysis_complete_email(), send_batch_complete_email(), dan send_analysis_failed_email(). Pengguna tier Enterprise menerima lampiran PDF yang ditingkatkan dengan citra satelit dan analisis NDVI, sementara pengguna tier gratis mendapat laporan ringkasan yang lebih sederhana.
Bekerja dengan Layanan Eksternal
Cara mengganti provider data satelit
- Buka file
.envAnda (atau buat dari.env.example). - Ubah variabel
DATA_PROVIDER. Pilihan:gee,planetary, ataucdse.DATA_PROVIDER=planetary - Jika beralih ke Planetary Computer, tambahkan
PLANETARY_COMPUTER_API_KEYdan instal paket tambahan:pip install planetary-computer pystac-client stackstac rioxarray - Restart server backend. Semua kode analisis menggunakan antarmuka
DataProvideryang sama, jadi tidak ada hal lain yang perlu diubah.
Cara menambahkan provider data baru
- Buat file baru di
backend/providers/, misalnyamy_provider.py. - Definisikan kelas yang meng-extend
DataProvider(dariproviders/base.py). - Implementasikan metode yang diperlukan:
initialize(),get_forest_loss_alerts(),get_radar_alerts(),get_land_cover(),get_satellite_imagery(), danget_ndvi_analysis(). - Setiap metode harus mengembalikan dataclass yang benar dari
providers/base.py(AlertResult,LandCoverResult,ImageryResult, atauNDVIResult). - Daftarkan di
providers/factory.pydengan menambahkan cabangelifdiget_provider(). - Atur
DATA_PROVIDER=my_providerdi.envdan restart.
Cara mengonfigurasi autentikasi GEE
- Buat service account di Google Cloud Console dengan akses Earth Engine.
- Unduh file kunci JSON untuk service account tersebut.
- Atur berikut ini di file
.envAnda:GEE_SERVICE_ACCOUNT=true GEE_PROJECT_ID=your-project-id GEE_SERVICE_ACCOUNT_EMAIL=sa@your-project.iam.gserviceaccount.com GEE_SERVICE_ACCOUNT_KEY_FILE=/path/to/keyfile.json - Restart backend. Provider GEE memanggil
ee.Initialize(credentials)saat startup menggunakan nilai-nilai ini.
Cara mengubah pengaturan koneksi database
- Buka file
.envAnda. - Atur kombinasi variabel berikut:
DB_HOST=localhost DB_PORT=5432 DB_NAME=eudr_forest_analyzer DB_USER=postgres DB_PASSWORD=secret DB_POOL_SIZE=5 DB_MAX_OVERFLOW=10 - Restart backend. Connection pool akan dibuat ulang dengan pengaturan baru.
- Untuk memverifikasi koneksi, periksa log startup untuk pesan “Database connection pool created” (tanpa error).
Mengapa Pilihan Desain Ini?
Pola Provider
Bayangkan abstraksi provider seperti adaptor listrik universal. Saat Anda bepergian ke negara lain, Anda mencolokkan adaptor yang berbeda, tetapi laptop Anda bekerja dengan cara yang sama. Factory pattern di factory.py memilih adaptor; sisa aplikasi tinggal mencolokkan.
GEE, Microsoft Planetary Computer, dan Copernicus Data Space semuanya menawarkan data satelit serupa — citra Sentinel-2, peta tutupan lahan, indikator kehilangan hutan — tetapi dengan API dan skema autentikasi yang sama sekali berbeda. Abstraksi provider menormalisasi semuanya ke dalam sekumpulan dataclass bersama: AlertResult, LandCoverResult, ImageryResult, dan NDVIResult.
Artinya, provider baru dapat ditambahkan (misalnya, vendor satelit komersial) tanpa menyentuh logika bisnis apa pun. Anda hanya perlu menulis lapisan translasi antara API mereka dan dataclass standar.
Mengapa Connection Pooling?
Tanpa connection pooling, setiap request HTTP akan membuka koneksi TCP baru ke PostgreSQL. Itu berarti TCP handshake, negosiasi SSL, autentikasi, dan setup koneksi — semuanya sebelum satu kueri pun dijalankan. Saat beban tinggi, ini bisa menambah ratusan milidetik per request dan menghabiskan batas koneksi database.
Dengan pooling, sekumpulan koneksi dibuat sekali saat startup dan dijaga tetap hidup. Saat sebuah request membutuhkan database, ia meminjam koneksi dari pool, menjalankan kuerinya, dan mengembalikannya. Pool juga menangani koneksi basi: ia dapat menguji setiap koneksi dengan SELECT 1 ringan sebelum menyerahkannya. Jika pengujian gagal (koneksi terputus, gangguan jaringan), pool secara diam-diam membuat koneksi baru.
Konfigurasi memiliki dua pengatur: pool_size (koneksi minimum yang selalu siap, default 5) dan max_overflow (berapa banyak koneksi tambahan yang dapat dibuat saat lonjakan lalu lintas, default 10). Ini menjaga penggunaan memori tetap terprediksi sambil tetap menangani lonjakan.
Jebakan GEE
Peringatan RADD (projects/radar-wur/raddalert/v1) dan ESA WorldCover (ESA/WorldCover/v200) keduanya adalah ImageCollection, bukan Image tunggal. Memuatnya dengan ee.Image("...") menyebabkan error: “Image.load: Asset is not an Image.”
Solusinya: gunakan ee.ImageCollection("...").first() untuk WorldCover (karena berisi satu mosaik global) atau filter berdasarkan rentang tanggal dan reduksi dengan .max() untuk RADD.
Jebakan umum lainnya: ImageCollection RADD berisi tipe citra campuran — beberapa memiliki band peringatan, yang lain memiliki band baseline. Memanggil .max() pada seluruh koleksi memicu error “Expected a homogeneous image collection.” Solusinya: .select('Alert') sebelum .max() agar semua citra memiliki struktur band yang sama.
GEE vs CDSE: Kapan Menggunakan Yang Mana
Kedua provider terimplementasi penuh, tetapi memiliki kekuatan dan arsitektur yang berbeda. Tabel berikut merangkum perbedaan utama:
| Aspek | GEE | CDSE |
|---|---|---|
| Arsitektur | Lapisan delegasi tipis (392 baris) — mendelegasikan ke layanan khusus | Mandiri dan komprehensif (1.920 baris) — semua logika dalam satu file |
| Kehilangan Hutan | Hansen GFC via GEE API (lossyear band) |
Global Forest Watch Data API (data-api.globalforestwatch.org) |
| Peringatan Radar | RADD via GEE ImageCollection | Global Forest Watch Data API (endpoint peringatan RADD) |
| Tutupan Lahan | ESA WorldCover via GEE | ESA WorldCover via Terrascope WMS/STAC (dengan mekanisme fallback) |
| Citra Satelit | Sentinel-2 via GEE | Sentinel-2 via SentinelHub Process API |
| Autentikasi | Service account key file + ee.Initialize() |
OAuth2 client credentials (CDSE_CLIENT_ID / CDSE_CLIENT_SECRET) |
| Fallback Offline | Tidak ada — memerlukan koneksi GEE | Data simulasi deterministik (hash MD5 geometri sebagai seed) |
| Terbaik Untuk | Lingkungan riset, akses ke petabyte data historis GEE | Deployment produksi, ketahanan tinggi, independen dari Google |
Deployment produksi saat ini menggunakan CDSE (DATA_PROVIDER=cdse). Provider GEE tetap tersedia sebagai alternatif untuk lingkungan pengembangan dan riset.
Referensi Layanan Eksternal
Dataset Satelit
| Dataset | ID | Resolusi | Cakupan | Band yang Digunakan |
|---|---|---|---|---|
| Hansen GFC | UMD/hansen/global_forest_change_2023_v1_11 |
30 m | Global (2001+) | lossyear |
| RADD | projects/radar-wur/raddalert/v1 |
10 m | Tropis (2019+) | Alert |
| ESA WorldCover | ESA/WorldCover/v200 |
10 m | Global (2021) | Map |
| Sentinel-2 L2A | COPERNICUS/S2_SR_HARMONIZED |
10 m | Global | B2-B4, B8 (RGB+NIR) |
Metode Antarmuka Provider
| Metode | Mengembalikan | Deskripsi |
|---|---|---|
initialize() |
bool |
Terhubung ke sumber data dan melakukan autentikasi |
get_forest_loss_alerts(geometry, start, end) |
AlertResult |
Peringatan kehilangan hutan (berbasis optik/Landsat) |
get_radar_alerts(geometry, start, end) |
AlertResult |
Peringatan deforestasi berbasis radar (Sentinel-1) |
get_land_cover(geometry, year) |
LandCoverResult |
Klasifikasi tutupan lahan (pohon, pertanian, air, dll.) |
get_satellite_imagery(geometry, date) |
ImageryResult |
Citra satelit warna asli untuk tanggal tertentu |
get_ndvi_analysis(geometry, baseline, current) |
NDVIResult |
Perbandingan indeks vegetasi antara dua tahun |
Variabel Lingkungan
| Variabel | Default | Deskripsi |
|---|---|---|
DATA_PROVIDER |
gee |
Provider satelit mana yang digunakan (gee, planetary, cdse) |
GEE_SERVICE_ACCOUNT |
false |
Gunakan autentikasi service account untuk GEE |
GEE_PROJECT_ID |
— | ID proyek Google Earth Engine |
DB_HOST |
localhost |
Host database PostgreSQL |
DB_POOL_SIZE |
5 |
Koneksi minimum yang dijaga di connection pool |
SMTP_HOST |
smtp.gmail.com |
Hostname server email SMTP |
Endpoint API Provider CDSE
| Layanan | URL | Metode | Tujuan |
|---|---|---|---|
| GFW Data API | data-api.globalforestwatch.org |
GET / POST |
Kueri data kehilangan hutan dan peringatan deforestasi |
| CDSE Identity | identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token |
POST |
Autentikasi OAuth2 untuk mendapatkan access token |
| SentinelHub Process | sh.dataspace.copernicus.eu/api/v1/process |
POST |
Mengambil citra satelit Sentinel-2 dan menghitung NDVI |
| Terrascope WMS | services.terrascope.be/wms |
GET |
Mengambil peta tutupan lahan ESA WorldCover (primer) |
| Terrascope STAC | services.terrascope.be/stac |
GET |
Mengambil tile tutupan lahan ESA WorldCover (fallback) |
| GFW RADD | data-api.globalforestwatch.org/dataset/gfw_radd_deforestation_alerts |
GET / POST |
Kueri peringatan deforestasi berbasis radar RADD |
Perbandingan Implementasi Provider
| Fitur | GEE | CDSE | Planetary |
|---|---|---|---|
| Kehilangan Hutan | Terimplementasi (Hansen GFC) | Terimplementasi (GFW Data API) | Belum diimplementasi |
| Peringatan Radar | Terimplementasi (RADD via GEE) | Terimplementasi (RADD via GFW) | Belum diimplementasi |
| Tutupan Lahan | Terimplementasi (ESA WorldCover via GEE) | Terimplementasi (Terrascope WMS/STAC) | Belum diimplementasi |
| Citra Satelit | Terimplementasi (Sentinel-2 via GEE) | Terimplementasi (SentinelHub Process API) | Terimplementasi (Sentinel-2 via STAC) |
| Analisis NDVI | Terimplementasi | Terimplementasi | Belum diimplementasi |
| Fallback Offline | Tidak ada | Data simulasi deterministik (MD5) | Tidak ada |
| Status Produksi | Tersedia (alternatif) | Aktif di produksi | Parsial |
Variabel Lingkungan CDSE
| Variabel | Default | Deskripsi |
|---|---|---|
DATA_PROVIDER |
gee |
Atur ke cdse untuk menggunakan provider Copernicus Data Space |
CDSE_CLIENT_ID |
— | OAuth2 client ID dari Copernicus Data Space (didaftarkan di dataspace.copernicus.eu) |
CDSE_CLIENT_SECRET |
— | OAuth2 client secret yang dipasangkan dengan CDSE_CLIENT_ID |
GFW_API_KEY |
— | API key untuk Global Forest Watch Data API (opsional, meningkatkan rate limit) |