Membuat Aplikasi Prediksi Cuaca dengan KNN dan TensorFlow Lite di Android
Artikel ini akan membimbing Anda untuk mengajarkan cara mengembangkan aplikasi cuaca yang memanfaatkan dua teknik kecerdasan buatan (AI) yakni KNN (K-Nearest Neighbor) dan TensorFlow Lite untuk memberikan rekomendasi berdasarkan data cuaca. Aplikasi ini akan mengambil data cuaca dari API OpenWeatherMap, mengolah data tersebut, dan memberikan prediksi cuaca berdasarkan prediksi dari model ML (Machine Learning).
Bab 1 Melatih Model AI dengan TensorFlow
1.1 Persiapkan Alat
Resource yang digunakan:
- Python: Untuk menulis dan menjalankan kode.
- scikit-learn: Library Python untuk machine learning, menyediakan alat untuk klasifikasi, regresi, clustering, dan evaluasi model.
- Pandas: Library Python untuk manipulasi dan analisis data tabular menggunakan struktur seperti DataFrame dan Series.
- Matplotlib: Library Python untuk membuat visualisasi data dalam berbagai jenis grafik seperti garis, batang, histogram, dan scatter plot.
- TensorFlow: Library Python untuk machine learning dan deep learning.
- Jupyter Notebook: Alat eksperimen interaktif untuk menulis dan menjalankan kode Python, serta menyajikan dokumentasi dan visualisasi.
- Postman: Aplikasi untuk pengujian API dengan mengirimkan permintaan HTTP dan memverifikasi respons.
- Android Studio: Lingkungan pengembangan terintegrasi (IDE) resmi untuk membangun aplikasi Android, mendukung Kotlin, Java, dan Jetpack Compose.
1.2 Install Python dan TensorFlow
Install Python
- Buka python.org, pilih versi Python terbaru yang sesuai dengan sistem operasi komputer Anda (Windows, macOS, atau Linux), dan unduh file instalasinya.
- Ikuti petunjuk instalasi. Pastikan untuk mencentang pilihan “Add Python to PATH” saat instalasi agar Python dapat digunakan di terminal atau command prompt.
- Untuk memeriksa apakah Python sudah terpasang, buka Command Prompt (Windows) atau Terminal (macOS/Linux) dan ketik perintah berikut:
python --version
Jika berhasil, Anda akan melihat versi Python yang terinstal.
Install TensorFlow
Setelah Python terinstal, buka terminal atau command prompt dan ketik perintah berikut untuk menginstal TensorFlow:
pip install tensorflow
Perintah ini akan mengunduh dan menginstal TensorFlow di komputer Anda. Tunggu hingga proses selesai.
Jalankan perintah berikut di Command Prompt (CMD) atau Terminal:
pip show tensorflow
Jika TensorFlow sudah terinstall, output yang muncul akan menampilkan informasi seperti ini:
Name: tensorflow
Version: 2.18.0
Summary: TensorFlow is an open source machine learning framework for everyone.
Home-page: https://www.tensorflow.org/
Author: Google Inc.
Author-email: packages@tensorflow.org
License: Apache 2.0
Location: C:\Users\Nanda Adisaputra\AppData\Roaming\Python\Python312\site-packages
Requires: tensorflow-intel
Required-by:
1.3 Install Library Tambahan untuk Data Preprocessing
Anda akan membutuhkan beberapa library Python untuk manipulasi data dan pembelajaran model.
- Pandas: Untuk mengolah data.
- scikit-learn: Untuk pemisahan data dan normalisasi.
- Jupyter Notebook: Untuk eksperimen interaktif dengan data.
Gunakan perintah ini untuk melihat apakah direktori Scripts
Python sudah ada di PATH:
$env:Path -split ";"
Jika hasilnya tidak ada baris seperti:
C:\Users\Nanda Adisaputra\AppData\Roaming\Python\Python312\Scripts
Maka PATH belum ditambahkan dengan benar.
Maka, Tambahkan PATH Secara Manual di PowerShell
$env:Path += ";C:\Users\Nanda Adisaputra\AppData\Roaming\Python\Python312\Scripts"
Untuk menginstal semua library ini, buka terminal atau command prompt, lalu ketikkan perintah berikut satu per satu:
pip install pandas
pip install scikit-learn
pip install jupyter
Lalu coba perintah:
jupyter --version
pygmentize --version
tensorboard --version
Jupyter Notebook adalah aplikasi berbasis web yang memungkinkan Anda untuk menulis dan menjalankan kode Python secara interaktif. Anda bisa menjalankannya dengan perintah:
jupyter notebook
Ini akan membuka Jupyter di browser Anda.
Bab 2 Mempersiapkan Dataset Cuaca
Aplikasi yang Digunakan
- Pandas: Library Python untuk analisis data yang menyediakan struktur data seperti DataFrame dan Series, memungkinkan manipulasi dan analisis data tabular dengan mudah.
- Jupyter Notebook: Aplikasi berbasis web untuk membuat dan berbagi dokumen komputasi yang berisi kode, visualisasi, dan teks naratif.
2.1 Menyiapkan Dataset Cuaca (weather_data.csv)
Dataset BMKG ini berisi informasi suhu, kelembaban, tekanan udara, dan status cuaca yang lebih terperinci.
Contoh Format Data Cuaca BMKG:
Dataset BMKG bisa didapatkan melalui API atau mengunduh langsung dari situs BMKG, biasanya dalam format CSV atau JSON. Data ini dapat meliputi kolom berikut:
temperature
(Suhu dalam °C)humidity
(Kelembaban dalam %)pressure
(Tekanan udara dalam hPa)weather_code
(Kode cuaca: 0 = cerah, 1 = berawan, 2 = hujan ringan, 3 = hujan lebat, 4 = mendung)weather_desc
(Deskripsi cuaca: cerah, berawan, hujan ringan, hujan lebat, mendung)
Contoh isi file weather_data_bmkg.csv
temperature,humidity,pressure,weather_code,weather_desc
30.5,65,1013,0,Cerah
28.3,75,1011,1,Berawan
27.0,85,1010,2,Hujan Ringan
25.5,90,1008,3,Hujan Lebat
32.0,70,1015,4,Mendung
29.5,80,1012,1,Berawan
26.5,82,1010,2,Hujan Ringan
24.0,95,1007,3,Hujan Lebat
31.0,60,1013,0,Cerah
30.0,78,1011,4,Mendung
2.2 Membaca Data dengan Pandas menggunakan Jupyter Notebook
2.2.1 Buka Terminal/Powershell dan Jalankan Jupyter Notebook
jupyter notebook
2.2.2 Buat File Notebook Baru
Klik New → Python 3 untuk membuat notebook baru.
2.2.3 Ketik Kode Berikut di Sel Jupyter Notebook:
import pandas as pd
# Membaca file CSV BMKG
df = pd.read_csv("weather_data_bmkg.csv") # Pastikan file berada di direktori yang sama
# Menampilkan 5 baris pertama
df.head()
Penjelasan Kode
import pandas as pd
→ Memuat pustaka Pandas untuk manipulasi data.pd.read_csv("weather_data_bmkg.csv")
→ Membaca file CSV BMKG ke dalam DataFrame Pandas.df.head()
→ Menampilkan 5 baris pertama dari dataset untuk pemeriksaan awal.
Output yang dihasilkan:
2.2.4 Menampilkan Data Berdasarkan Kategori Cuaca
Menampilkan Cuaca Cerah:
df[df["weather_code"] == 0]
Output yang dihasilkan:
Menampilkan Cuaca Berawan:
df[df["weather_code"] == 1]
Output yang dihasilkan:
Menampilkan Cuaca Hujan Ringan:
df[df["weather_code"] == 2]
Output yang dihasilkan:
Menampilkan Cuaca Hujan Lebat:
df[df["weather_code"] == 3]
Output yang dihasilkan:
Menampilkan Cuaca Mendung:
df[df["weather_code"] == 4]
Output yang dihasilkan:
2.2.5 Menambahkan Fitur Visualisasi Cuaca
Kita dapat memvisualisasikan data cuaca untuk memahami pola cuaca dengan lebih baik menggunakan Matplotlib.
Anda dapat menginstal modul matplotlib
dengan menjalankan perintah berikut di terminal atau command prompt:
pip install matplotlib
Contoh Visualisasi Data Suhu:
import matplotlib.pyplot as plt
# Membuat plot suhu
plt.figure(figsize=(10,6))
plt.plot(df["temperature"], label="Suhu (°C)", marker="o", color="b")
plt.title("Grafik Suhu Cuaca")
plt.xlabel("Indeks Data")
plt.ylabel("Suhu (°C)")
plt.legend()
plt.grid(True)
plt.show()
Output yang dihasilkan:
Bab 3 Menyiapkan Data untuk Pelatihan
3.1 Pisahkan Data Fitur dan Target
Untuk dataset BMKG, kita memiliki beberapa kolom, termasuk suhu, kelembaban, tekanan udara, dan deskripsi cuaca. Kita akan menggunakan fitur-fitur seperti suhu, kelembaban, dan tekanan udara untuk memprediksi status cuaca (weather_code
).
- Fitur adalah data yang akan digunakan untuk memprediksi hasil (misalnya suhu, kelembaban, dan tekanan udara).
- Target adalah hasil yang ingin diprediksi (misalnya apakah cuaca cerah atau hujan).
Misalnya, kita ingin memprediksi apakah cuaca akan hujan berdasarkan suhu, kelembaban, dan tekanan udara. Tambahkan kode berikut di file Python Anda:
import pandas as pd
# Membaca data dari file CSV
data = pd.read_csv("weather_data_bmkg.csv")
# Menampilkan 5 baris pertama untuk memeriksa data
print(data.head())
# Pisahkan fitur dan target
X = data[['temperature', 'humidity', 'pressure']] # Fitur
y = data['weather_code'] # Target (misalnya, 0=cerah, 1=berawan, 2=hujan ringan, dsb.)
Output yang dihasilkan:
3.2 Normalisasi Data
Karena data kita memiliki fitur dengan rentang nilai yang berbeda (misalnya suhu bisa antara 20°C hingga 35°C, kelembaban antara 60% hingga 100%), kita akan menormalkan data untuk memastikan bahwa semua fitur memiliki skala yang sama.
Kita akan menggunakan StandardScaler
dari scikit-learn untuk ini. Tambahkan kode berikut:
from sklearn.preprocessing import StandardScaler
# Normalisasi data fitur menggunakan StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
3.3 Pisahkan Data Menjadi Pelatihan dan Pengujian
Untuk menguji model yang kita buat, kita akan membagi dataset menjadi dua bagian: 80% untuk data pelatihan dan 20% untuk data pengujian. Ini memungkinkan kita untuk melatih model dengan data yang lebih banyak dan menguji model dengan data yang belum pernah dilihat sebelumnya.
Tambahkan kode berikut:
from sklearn.model_selection import train_test_split
# Pisahkan data menjadi data pelatihan dan pengujian (80% pelatihan, 20% pengujian)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# Menampilkan jumlah data pelatihan dan pengujian
print(f"Jumlah data pelatihan: {len(X_train)}")
print(f"Jumlah data pengujian: {len(X_test)}")
Output yang dihasilkan:
3.4 Verifikasi Data
Anda dapat memverifikasi bahwa fitur dan target sudah terpisah dengan benar, dan bahwa data telah dinormalisasi dan dibagi dengan benar:
# Menampilkan beberapa contoh data pelatihan
print("Data pelatihan pertama:")
print(X_train[:5]) # Menampilkan 5 baris pertama dari data pelatihan
# Menampilkan beberapa label target pelatihan
print("Label target pelatihan pertama:")
print(y_train[:5]) # Menampilkan 5 label pertama dari data pelatihan
Output yang dihasilkan
Bab 4 Melatih Model dengan TensorFlow
Untuk membangun model prediksi cuaca menggunakan TensorFlow, kita akan membuat jaringan saraf sederhana dengan Keras, bagian dari TensorFlow. Berikut adalah langkah-langkah yang lebih terperinci untuk membangun, melatih, dan mengevaluasi model.
4.1 Membangun Model dengan Keras
Di bagian ini, kita akan membuat model jaringan saraf sederhana menggunakan lapisan Dense. Lapisan pertama menerima input dengan jumlah fitur yang sesuai dengan data pelatihan, dan lapisan terakhir memiliki satu neuron untuk output (0 atau 1 untuk cuaca cerah atau hujan). Fungsi aktivasi yang digunakan adalah ReLU untuk lapisan tersembunyi dan sigmoid untuk output (karena ini adalah masalah klasifikasi biner).
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense
# Membangun model menggunakan Input sebagai lapisan pertama
model = tf.keras.Sequential([
Input(shape=(X_train.shape[1],)), # Lapisan input dengan bentuk fitur
Dense(64, activation='relu'), # Lapisan tersembunyi pertama
Dense(64, activation='relu'), # Lapisan tersembunyi kedua
Dense(1, activation='sigmoid') # Lapisan output
])
# Menyusun model dengan optimizer 'adam' dan loss 'binary_crossentropy'
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
Penjelasan:
Input(shape=(X_train.shape[1],))
: Ini adalah cara yang benar untuk mendefinisikan lapisan input pada model Sequential.shape
mendefinisikan dimensi input (jumlah fitur dalam dataset Anda).Dense(64, activation='relu')
: Lapisan tersembunyi pertama dan kedua menggunakan fungsi aktivasi ReLU.Dense(1, activation='sigmoid')
: Lapisan output menggunakan fungsi aktivasi sigmoid, karena ini adalah masalah klasifikasi biner (0 atau 1).
4.2 Latih Model
Sekarang, kita melatih model dengan data pelatihan yang sudah disiapkan sebelumnya. Fungsi fit
digunakan untuk melatih model selama beberapa epoch, yang berarti jumlah iterasi atas seluruh dataset.
# Latih model menggunakan data pelatihan
model.fit(X_train, y_train, epochs=10, batch_size=32)
epochs=10
: Menentukan bahwa model akan dilatih selama 10 iterasi atas seluruh dataset.batch_size=32
: Menentukan jumlah sampel data yang akan diproses dalam satu iterasi sebelum update parameter model.
Penjelasan:
Proses pelatihan memungkinkan model untuk belajar dari pola-pola dalam data cuaca dan membuat prediksi berdasarkan data tersebut. Setelah 10 epoch, model akan terlatih dan siap untuk dievaluasi.
Output yang dihasilkan:
4.3 Evaluasi Model
Setelah melatih model, kita akan menguji akurasinya menggunakan data pengujian yang sebelumnya sudah dipisahkan. Fungsi evaluate
akan memberikan metrik akurasi pada data pengujian.
# Evaluasi model menggunakan data pengujian
loss, accuracy = model.evaluate(X_test, y_test)
# Menampilkan akurasi model
print(f'Model Accuracy: {accuracy * 100:.2f}%')
Output yang dihasilkan :
Penjelasan:
loss
: Ini adalah nilai fungsi loss setelah evaluasi model. Ini menunjukkan seberapa baik model dalam memprediksi output yang benar.accuracy
: Ini menunjukkan persentase prediksi yang benar pada data pengujian. Nilai ini akan memberikan gambaran seberapa baik model dapat memprediksi cuaca berdasarkan suhu, kelembaban, dan tekanan udara.
Dengan evaluasi yang baik, model Anda dapat memberikan prediksi yang akurat mengenai status cuaca (misalnya cerah atau hujan). Model yang lebih kompleks atau pelatihan lebih lanjut dapat dilakukan untuk meningkatkan akurasi.
Menggunakan TensorFlow dan Keras, Anda dapat dengan mudah membangun dan melatih model klasifikasi cuaca. Data seperti suhu, kelembaban, dan tekanan udara dapat digunakan untuk memprediksi cuaca, yang bisa diterapkan dalam banyak kasus dunia nyata — seperti peramalan cuaca atau aplikasi ramalan cuaca berbasis AI. Seperti saat Anda mengajarkan berbagai bahasa pemrograman dalam kelas, model ini juga membutuhkan latihan yang baik dan pengujian secara berkelanjutan untuk memastikan hasil yang optimal!
Bab 5 Menyimpan dan Memuat Kembali Model
Setelah melatih model, kita dapat menyimpannya dalam format file .keras. Format ini berguna karena file .keras adalah format penyimpanan standar untuk model Keras (bagian dari TensorFlow), yang memungkinkan kita untuk memuat dan menggunakan kembali model di aplikasi lain, seperti aplikasi Android.
5.1 Menyimpan Model
Untuk menyimpan model, kita akan menggunakan metode save()
dari Keras. Model akan disimpan dalam format .keras yang disarankan oleh TensorFlow.
# Menyimpan model dalam format .keras yang lebih disarankan
model.save('weather_model.keras')
print("Model saved as 'weather_model.keras'")
Penjelasan:
model.save('weather_model.keras')
: Fungsi ini menyimpan seluruh model, termasuk struktur, bobot, dan konfigurasi pelatihan (seperti optimizer) dalam file weather_model.keras.- File .keras ini dapat digunakan kembali di aplikasi lain (misalnya, aplikasi Android) tanpa perlu melatih ulang model dari awal.
Output yang dihasilkan :
5.2 Memuat Model Kembali dengan Kompilasi Ulang
Setelah Anda menyimpan model, Anda dapat memuatnya kembali dan mengompilasi ulang model tersebut jika diperlukan untuk melakukan prediksi atau melanjutkan pelatihan. Untuk memuat model tanpa mengompilasinya, Anda bisa menggunakan parameter compile=False
. Ini berguna jika Anda hanya ingin menggunakan model untuk prediksi dan tidak ingin mengompilasi model lagi saat memuatnya.Kode untuk Memuat Model dengan Kompilasi Ulang:
from tensorflow.keras.models import load_model
# Memuat model yang telah disimpan tanpa kompilasi
model_loaded = load_model('weather_model.keras', compile=False) # Memuat model tanpa kompilasi awal
print("Model loaded successfully.")
# Kompilasi ulang model jika diperlukan
model_loaded.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
print("Model compiled successfully.")
Penjelasan:
load_model('weather_model.keras', compile=False)
: Fungsi ini digunakan untuk memuat model yang telah disimpan tanpa secara otomatis mengompilasinya. Ini berguna jika Anda hanya ingin menggunakan model untuk prediksi dan tidak melibatkan proses pelatihan lebih lanjut. Dengan menggunakancompile=False
, Anda dapat menghindari kompilasi yang tidak diperlukan saat memuat model.model_loaded.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
: Setelah model dimuat, jika Anda ingin melanjutkan pelatihan atau ingin menggunakan optimasi tertentu, Anda perlu mengompilasi model ulang. Di sini, kita menggunakan optimizeradam
, loss functionbinary_crossentropy
(karena ini adalah masalah klasifikasi biner), danaccuracy
sebagai metrik untuk mengevaluasi model.
Mengapa Menggunakan compile=False
?
compile=False
digunakan saat Anda hanya membutuhkan model untuk prediksi, dan Anda tidak perlu segera melatihnya lagi. Ini mempercepat proses pemuatan model.- Setelah model dimuat, Anda bisa mengompilasi ulang model jika ingin melanjutkan pelatihan atau jika Anda membutuhkan konfigurasi optimizer atau loss function yang berbeda.
Bagaimana Menggunakan Model yang Dimuat untuk Prediksi?
Setelah model berhasil dimuat dan dikompilasi, Anda dapat langsung menggunakannya untuk prediksi.
Contoh Prediksi:
# Melakukan prediksi dengan model yang telah dimuat dan dikompilasi
predictions = model_loaded.predict(X_test)
print("Predictions:", predictions)
Kesimpulan:
- Anda dapat memuat model tanpa kompilasi menggunakan
compile=False
untuk mempercepat proses jika hanya melakukan prediksi. - Jika Anda ingin melanjutkan pelatihan atau melakukan evaluasi, Anda perlu mengompilasi ulang model menggunakan
model.compile()
dengan parameter yang sesuai.
Output yang dihasilkan:
Bab 6 Mengonversi Model ke Format TensorFlow Lite
6. 1 Mengonversi Model ke Format TensorFlow Lite
Setelah model selesai dilatih dan disimpan dalam format .keras
atau .h5
, langkah berikutnya adalah mengonversi model tersebut ke format TensorFlow Lite (.tflite
). Format ini lebih efisien dan dioptimalkan untuk digunakan di perangkat Android, yang memiliki keterbatasan sumber daya (seperti prosesor dan memori).
Langkah-langkah untuk mengonversi model ke format TensorFlow Lite:
6.1.1 Memuat Model yang Telah Disimpan:
Anda perlu memuat modelyang telah disimpan dalam format .keras
atau .h5
. Jika model Anda disimpan dalam format .keras
, Anda bisa memuatnya dengan load_model()
dari Keras.
6.1.2 Konversi Model ke Format TensorFlow Lite:
TensorFlow menyediakan TFLiteConverter
untuk mengonversi model Keras ke format .tflite
. Anda cukup menggunakan TFLiteConverter.from_keras_model()
untuk konversi.
6.1.3 Simpan Model yang Telah Dikonversi:
Setelah model berhasil dikonversi ke format .tflite
, Anda perlu menyimpannya dalam file .tflite
. File ini kemudian dapat digunakan di aplikasi Android.
Berikut adalah kode lengkapnya:
import tensorflow as tf
# Memuat model yang telah disimpan
model = tf.keras.models.load_model('weather_model.keras') # Ganti dengan 'weather_model.h5' jika menggunakan format .h5
# Konversi model ke format TensorFlow Lite
converter = tf.lite.TFLiteConverter.from_keras_model(model) # Menggunakan model Keras untuk konversi
tflite_model = converter.convert() # Melakukan konversi model ke format .tflite
# Simpan model .tflite ke dalam file
with open('weather_model.tflite', 'wb') as f:
f.write(tflite_model) # Menulis model TensorFlow Lite ke file .tflite
print("Model berhasil dikonversi dan disimpan sebagai 'weather_model.tflite'")
Penjelasan:
model = tf.keras.models.load_model('weather_model.keras')
: Fungsi ini digunakan untuk memuat model Keras yang sudah disimpan sebelumnya. Jika Anda menggunakan format .h5
, pastikan untuk mengganti 'weather_model.keras'
dengan 'weather_model.h5'
.
converter = tf.lite.TFLiteConverter.from_keras_model(model)
: Fungsi ini membuat objek TFLiteConverter
yang digunakan untuk mengonversi model Keras ke format TensorFlow Lite. Pastikan model Anda adalah model Keras yang telah dilatih dengan benar sebelum mengonversinya.
tflite_model = converter.convert()
: Perintah ini melakukan konversi model ke format .tflite
. Ini menghasilkan objek tflite_model
yang merupakan representasi model dalam format yang dapat digunakan di perangkat mobile dan perangkat edge lainnya.
with open('weather_model.tflite', 'wb') as f: f.write(tflite_model)
: Setelah konversi selesai, kita menyimpan model .tflite
dalam file. Menggunakan mode 'wb'
memastikan bahwa data biner dari model .tflite
ditulis ke file dengan benar.
Output yang dihasilkan :
Mengapa Menggunakan TensorFlow Lite?
- Efisiensi: TensorFlow Lite dirancang untuk perangkat dengan keterbatasan sumber daya (seperti ponsel Android dan perangkat edge lainnya), mengurangi ukuran model dan meningkatkan kecepatan inferensi.
- Portabilitas: Format
.tflite
dapat digunakan di banyak platform, termasuk Android, iOS, dan perangkat embedded lainnya.
Langkah Selanjutnya:
Setelah model diubah menjadi format .tflite
, Anda dapat memuat model tersebut di aplikasi Android menggunakan TensorFlow Lite SDK untuk melakukan prediksi di perangkat Android tanpa memerlukan koneksi internet atau proses pelatihan.
Dengan langkah-langkah ini, Anda dapat memastikan bahwa model cuaca yang telah dilatih siap digunakan di aplikasi Android dengan performa yang efisien.
Bab 7 Pembuatan Aplikasi Cuaca dengan AI di Android Studio
Teknologi yang Digunakan
- IDE: Android Studio
- Bahasa: Kotlin
- ML Framework: TensorFlow Lite
- API Cuaca: OpenWeatherMap
Alur Program
MainActivity.kt: Di sini, UI untuk mengambil input dari pengguna (nama kota) dan menampilkan hasil cuaca bersama dengan rekomendasi cuaca berdasarkan model prediksi yang menggunakan KNN dan TensorFlow Lite.
WeatherData: Model untuk menyimpan data cuaca seperti suhu, kelembapan, tekanan udara, dan kecepatan angin.
WeatherRepository: Mengambil data cuaca dari API menggunakan Retrofit dan melakukan prediksi cuaca dengan TensorFlow Lite.
WeatherMLModel: Tempat untuk memuat model TensorFlow Lite dan mengolah prediksi menggunakan data cuaca (temperatur, kelembapan, tekanan, kecepatan angin).
WeatherViewModel: Mengelola data cuaca yang diterima dan logika bisnis untuk memprosesnya, serta menyiapkan data untuk ditampilkan di UI.
WeatherViewModelFactory: Digunakan untuk membuat instance WeatherViewModel
dengan dependensi yang benar.
7. 1 Menyiapkan API OpenWeatherMap
Sebelum memulai kode, pastikan Anda memiliki API key dari OpenWeatherMap. Daftarkan akun dan dapatkan API key yang akan digunakan untuk mengambil data cuaca.
Contoh URL lengkap untuk Jakarta:
https://api.openweathermap.org/data/2.5/weather?q=Jakarta&appid=your_api_key&units=metric&lang=id
Dengan mengganti your_api_key
dengan API key yang valid, dan Jakarta
dengan nama kota yang Anda inginkan, Anda dapat mengirim permintaan GET untuk mendapatkan data cuaca dari API OpenWeatherMap.
7.2 Menyiapkan Model TensorFlow Lite
Anda perlu model TensorFlow Lite yang telah dilatih untuk memprediksi rekomendasi cuaca. Model ini bisa dilatih dengan menggunakan dataset cuaca dan disesuaikan dengan kebutuhan.
7.3 Menyiapkan Struktur Aplikasi
app
├── manifests
│ └── AndroidManifest.xml
├── kotlin+java
│ └── com.nandaadisaputra.weather
│ ├── helper
│ │ └── WeatherViewModelFactory
│ ├── model
│ │ ├── WeatherData
│ │ └── WeatherMLModel
│ ├── network
│ │ ├── WeatherResponse
│ │ ├── WeatherResult
│ │ └── WeatherService
│ ├── repository
│ │ └── WeatherRepository
│ └── ui
│ ├── MainActivity
│ └── WeatherViewModel
├── assets
│ └── weather_model.tflite
├── res
│ ├── drawable
│ ├── layout
│ │ └── activity_main.xml
│ ├── mipmap
│ ├── values
│ │ ├── colors.xml
│ │ └── strings.xml
│ └── xml
7.4 Menambahkan API Key ke Gradle Properties
7.4.1 Buka file gradle.properties
(di root proyek Android).
7.4.2 Tambahkan API Key dengan format berikut:
WEATHER_API_KEY=a5ae9507b408198ce9a914988e130695
7.5 Menggunakan API Key dalam build.gradle.kts
(Module: app)
7.5.1 Buka app/build.gradle.kts
.
7.5.2 Tambahkan baris berikut di dalam blok android.defaultConfig
:
val weatherApiKey: String = project.findProperty("WEATHER_API_KEY") as? String ?: ""
buildConfigField("String", "WEATHER_API_KEY", "\"$weatherApiKey\"")
7.5.3 Pastikan fitur BuildConfig diaktifkan:
buildFeatures {
buildConfig = true
}
7.6 Menggunakan API Key dalam Kode Kotlin
7.6.1 Panggil API Key di dalam kode Kotlin menggunakan BuildConfig
val apiKey = BuildConfig.WEATHER_API_KEY
7.6.2 Gunakan apiKey
saat melakukan permintaan ke API OpenWeatherMap.
7.7 Dependensi
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
// Retrofit dan Converter Gson
implementation(libs.retrofit)
implementation(libs.retrofit.converter.gson)
// TensorFlow Lite
implementation(libs.tensorflow.lite)
// Kotlin Coroutines
implementation(libs.kotlinx.coroutines.android)
// Lifecycle ViewModel & LiveData
implementation(libs.lifecycle.viewmodel.ktx)
implementation(libs.lifecycle.livedata.ktx)
// Unit Testing
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
Penjelasan:
- Retrofit → Menggunakan API dari OpenWeather.
- TensorFlow Lite → Untuk model pembelajaran mesin.
- Kotlin Coroutines → Untuk operasi asynchronous.
- Lifecycle ViewModel & LiveData → Untuk mengelola data secara reaktif.
7.8 Konfigurasi Versi di libs.versions.toml
[versions]
agp = "8.6.1"
kotlin = "1.9.0"
coreKtx = "1.15.0"
junit = "4.13.2"
appcompat = "1.7.0"
material = "1.12.0"
retrofit = "2.9.0"
tensorflow-lite = "2.14.0"
hilt = "2.51"
[libraries]
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
tensorflow-lite = { group = "org.tensorflow", name = "tensorflow-lite", version.ref = "tensorflow-lite" }
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" }
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
📌 Keuntungan menggunakan libs.versions.toml
:
- Menjaga versi tetap konsisten di seluruh proyek.
- Mudah diperbarui saat ada versi terbaru.
7.9 Menambahkan Resource Warna dan String.
7.9.1 colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Warna yang digunakan dalam UI -->
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="grey">#808080</color> <!-- Untuk hint text -->
<color name="colorPrimary">#6200EE</color> <!-- Warna utama untuk tombol dan elemen lainnya -->
<color name="colorBackground">#F1F1F1</color> <!-- Warna latar belakang -->
</resources>
7.9.2 strings.xml
<resources>
<string name="app_name">Weather</string>
<string name="hint_city">Masukkan nama kota!</string>
<string name="weather_info">
<![CDATA[
Area : %1$s
Suhu : %2$d°C
Kelembapan: %3$d%%
Kecepatan Angin: %4$.1f m/s
Tekanan Udara : %5$d hPa
]]>
</string>
<string name="weather_prediction">Prediksi Cuaca: </string>
<string name="enter_city_name">Masukkan nama kota</string>
<string name="get_weather_prediction">Dapatkan Prediksi Cuaca</string>
<string name="weather">Cuaca:</string>
<string name="current_weather">Cuaca Sekarang</string>
</resources>
7.9.3 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity"
android:padding="16dp"
android:background="@color/colorBackground">
<!-- Judul -->
<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/current_weather"
android:textSize="24sp"
android:textColor="@color/black"
android:gravity="center"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="40dp"/>
<!-- CardView untuk input dan tombol -->
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:elevation="8dp"
app:cardCornerRadius="16dp"
app:layout_constraintTop_toBottomOf="@id/title_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="16dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<!-- Input untuk nama kota -->
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:boxStrokeColor="@color/colorPrimary"
app:hintAnimationEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/city_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/enter_city_name"
android:textColor="@color/black"
android:textColorHint="@color/grey"
android:inputType="text"
android:padding="16dp"
android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout>
<!-- Tombol untuk mengambil data cuaca -->
<Button
android:id="@+id/fetch_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/get_weather_prediction"
android:textColor="@android:color/white"
android:backgroundTint="@color/colorPrimary"
android:padding="12dp"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/city_input"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<!-- Menampilkan data cuaca -->
<TextView
android:id="@+id/result_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/weather"
android:textSize="18sp"
android:textColor="@color/black"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/fetch_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<!-- Menampilkan hasil prediksi cuaca -->
<TextView
android:id="@+id/prediction_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/weather_prediction"
android:textSize="18sp"
android:textColor="@color/black"
app:layout_constraintTop_toBottomOf="@id/result_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
7.10 MainActivity.kt
MainActivity adalah komponen utama yang menampilkan UI dan berinteraksi dengan ViewModel. Di sini kita akan mengambil input dari pengguna (nama kota), memanggil ViewModel untuk mengambil data cuaca, dan menampilkan hasil prediksi rekomendasi cuaca secara real-time.
package com.nandaadisaputra.weather.ui
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.nandaadisaputra.weather.BuildConfig
import com.nandaadisaputra.weather.R
import com.nandaadisaputra.weather.repository.WeatherRepository
import com.nandaadisaputra.weather.helper.WeatherViewModelFactory
import com.nandaadisaputra.weather.model.WeatherMLModel
import com.nandaadisaputra.weather.network.WeatherService
import com.nandaadisaputra.weather.network.getFormattedWeatherInfo
import kotlinx.coroutines.launch
// MainActivity adalah kelas utama yang menjalankan aplikasi cuaca
class MainActivity : AppCompatActivity() {
// Deklarasi variabel UI yang digunakan untuk menampilkan input dan hasil
private lateinit var cityInput: EditText // Input untuk nama kota
private lateinit var resultText: TextView // Menampilkan hasil cuaca
private lateinit var fetchButton: Button // Tombol untuk mengambil data cuaca
private lateinit var predictionText: TextView // Menampilkan prediksi cuaca
// Inisialisasi ViewModel dengan Factory yang menerima WeatherRepository dan WeatherMLModel
private val viewModel: WeatherViewModel by viewModels {
WeatherViewModelFactory(
WeatherRepository(WeatherService.create(), WeatherMLModel(applicationContext)),
WeatherMLModel(applicationContext)
)
}
// Fungsi onCreate dijalankan saat activity dimulai
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) // Menetapkan layout untuk activity
// Inisialisasi komponen UI dari layout XML
cityInput = findViewById(R.id.city_input)
resultText = findViewById(R.id.result_text)
fetchButton = findViewById(R.id.fetch_button)
predictionText = findViewById(R.id.prediction_text)
// Memulai observasi terhadap perubahan data cuaca dari ViewModel
observeViewModel()
// Menambahkan event listener untuk tombol "fetchButton" ketika diklik
fetchButton.setOnClickListener {
// Mendapatkan nama kota dari input pengguna
val cityName = cityInput.text.toString()
// Memeriksa apakah input nama kota tidak kosong
if (cityName.isNotEmpty()) {
// Mengambil API Key dari BuildConfig (diambil dari gradle.properties)
val apiKey = BuildConfig.WEATHER_API_KEY
// Menggunakan Coroutine untuk memanggil fungsi fetchWeatherWithRecommendation secara asinkron
lifecycleScope.launch {
// Memanggil fungsi fetchWeatherWithRecommendation dan fetch recommendation
viewModel.fetchWeatherWithRecommendation(city = cityName, apiKey = apiKey)
}
} else {
// Menampilkan pesan jika input nama kota kosong
resultText.text = getString(R.string.hint_city)
}
}
}
// Fungsi untuk mengamati perubahan data yang diterima oleh ViewModel
private fun observeViewModel() {
// Mengamati data cuaca yang diterima dari ViewModel
viewModel.weatherData.observe(this, Observer { weather ->
// Menampilkan informasi cuaca terformat
resultText.text = weather.getFormattedWeatherInfo()
// Menampilkan prediksi cuaca berdasarkan model machine learning
viewModel.weatherRecommendation.observe(this, Observer { recommendation ->
predictionText.text = if (!recommendation.isNullOrEmpty()) {
getString(R.string.weather_prediction) + " " + recommendation
} else {
getString(R.string.weather_prediction) // Hanya "Prediksi Cuaca:" tanpa nilai
}
})
})
// Mengamati error yang mungkin terjadi selama proses pengambilan data cuaca
viewModel.error.observe(this, Observer { errorMessage ->
// Menampilkan pesan error jika terjadi masalah dalam mengambil data
resultText.text = errorMessage
})
}
}
Penjelasan:
- UI Components:
cityInput
: EditText untuk memasukkan nama kota.resultText
: TextView untuk menampilkan informasi cuaca dari API.predictionText
: TextView baru yang menampilkan prediksi rekomendasi cuaca hasil dari model ML (KNN + TensorFlow).- ViewModel dan LiveData:
- ViewModel digunakan untuk memisahkan logika bisnis dari UI dan mengamati perubahan data (
LiveData
). observeViewModel()
digunakan untuk mengamati data cuaca dan menampilkan hasil prediksi ke UI.
7.11 WeatherData.kt
Model data ini menyimpan informasi cuaca yang akan diproses oleh aplikasi, seperti suhu, kelembaban, kecepatan angin, dan tekanan udara.
package com.nandaadisaputra.weather.model
data class WeatherData(
val temp: Float, // Temperatur dalam Celsius
val humidity: Int, // Kelembaban dalam persen
val windSpeed: Float, // Kecepatan angin dalam km/h
val pressure: Float, // Tekanan udara dalam hPa
val weatherCategory: String = "Tidak Terdefinisi" // Kategori cuaca (Opsional)
) {
// Validasi untuk memastikan data cuaca valid dan sesuai dengan batasan
init {
require(humidity in 0..100) { "Kelembaban harus antara 0 hingga 100" }
require(temp >= -100 && temp <= 100) { "Suhu harus berada dalam rentang yang wajar" }
require(windSpeed >= 0) { "Kecepatan angin tidak bisa negatif" }
require(pressure >= 0) { "Tekanan udara tidak bisa negatif" }
}
}
Penjelasan:
- WeatherData: Data yang digunakan untuk mengirimkan informasi cuaca ke dalam model TensorFlow Lite dan KNN.
7.12 WeatherResponse.kt
Model ini digunakan untuk memetakan respons dari API OpenWeatherMap.
package com.nandaadisaputra.weather.network
import com.google.gson.annotations.SerializedName
// Data kelas untuk respon cuaca
data class WeatherResponse(
val name: String, // Nama kota
val main: Main, // Data utama cuaca (temperatur, kelembapan, tekanan)
val weather: List<Weather>, // Daftar kondisi cuaca
val wind: Wind // Kecepatan angin
)
data class Main(
val temp: Float, // Suhu dalam derajat Celsius
val humidity: Int, // Kelembapan dalam persentase
val pressure: Float // Tekanan udara dalam hPa
)
data class Weather(
val main: String, // Nama kondisi cuaca (misalnya, "Clear", "Rain")
@SerializedName("description") val description: String // Deskripsi kondisi cuaca (misalnya, "clear sky")
)
data class Wind(
val speed: Float // Kecepatan angin dalam m/s
)
Penjelasan:
- WeatherResponse: Mewakili format data yang diterima dari API, yang mencakup informasi cuaca seperti suhu, kelembaban, dan deskripsi cuaca.
- Main dan Weather: Digunakan untuk memetakan bagian-bagian dari respons API yang relevan.
7.13 WeatherResult.kt
Model ini adalah hasil prediksi cuaca yang akan ditampilkan di UI setelah mendapatkan data dari API dan model ML.
package com.nandaadisaputra.weather.network
data class WeatherResult(
val city: String, // Nama kota
val temp: Float, // Suhu dalam derajat Celsius
val humidity: Int, // Kelembapan dalam persentase
val windSpeed: Float, // Kecepatan angin dalam m/s
val pressure: Float, // Tekanan udara dalam hPa
val weatherCategory: String // Kategori cuaca (misalnya: "Clear", "Rain")
)
// Fungsi untuk memformat cuaca menjadi string yang bisa ditampilkan
fun WeatherResult.getFormattedWeatherInfo(): String {
return "Kota: $city\n" +
"Suhu: $temp°C\n" +
"Kelembaban: $humidity%\n" +
"Kecepatan Angin: $windSpeed m/s\n" +
"Tekanan: $pressure hPa\n" +
"Kondisi: $weatherCategory"
}
Penjelasan:
- WeatherResult: Menyimpan hasil akhir yang akan ditampilkan di UI, termasuk rekomendasi cuaca yang dihasilkan oleh model ML.
7.14 WeatherService.kt
WeatherService
berfungsi untuk berkomunikasi dengan API OpenWeatherMap menggunakan Retrofit.
package com.nandaadisaputra.weather.network
// Mengimpor BuildConfig untuk mengakses konstanta BASE_URL
import com.nandaadisaputra.weather.BuildConfig.BASE_URL
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
// Interface untuk mendefinisikan endpoint yang akan dipanggil oleh Retrofit
interface WeatherService {
// Mendefinisikan endpoint API untuk mendapatkan data cuaca berdasarkan nama kota
@GET("weather")
suspend fun getWeather(
@Query("q") city: String, // Parameter query untuk nama kota
@Query("appid") apiKey: String, // API key untuk otentikasi
@Query("units") units: String // Parameter untuk menentukan satuan suhu (misalnya "metric" untuk Celcius)
): WeatherResponse? // Fungsi ini mengembalikan response dalam bentuk WeatherResponse, bisa null jika gagal
// Companion object untuk membuat instance Retrofit dan mengonfigurasi WeatherService
companion object {
// Fungsi untuk membuat dan mengonfigurasi instance Retrofit
fun create(): WeatherService {
val retrofit = Retrofit.Builder()
// Menggunakan BASE_URL yang disediakan oleh BuildConfig, diambil dari file build.gradle
.baseUrl(BASE_URL)
// Menambahkan converter Gson untuk parsing response API menjadi objek Kotlin
.addConverterFactory(GsonConverterFactory.create())
.build() // Membangun objek Retrofit
// Mengembalikan instance WeatherService yang siap digunakan untuk panggilan API
return retrofit.create(WeatherService::class.java)
}
}
}
Penjelasan:
- Retrofit: Digunakan untuk mengambil data cuaca dari API.
- GET request: Digunakan untuk mengakses data cuaca berdasarkan nama kota yang diberikan.
7.15 WeatherRepository.kt
Repository ini menggabungkan data dari API dan melakukan prediksi dengan menggunakan model ML.
package com.nandaadisaputra.weather.repository
import com.nandaadisaputra.weather.model.WeatherData
import com.nandaadisaputra.weather.model.WeatherMLModel
import com.nandaadisaputra.weather.network.WeatherResult
import com.nandaadisaputra.weather.network.WeatherService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class WeatherRepository(private val api: WeatherService, private val mlModel: WeatherMLModel) {
// Fungsi untuk mengambil data cuaca dari API dan memberikan rekomendasi dari model ML
suspend fun fetchWeather(cityName: String, apiKey: String): WeatherResult {
return withContext(Dispatchers.IO) {
// Memastikan API key tidak kosong
if (apiKey.isBlank()) {
throw IllegalArgumentException("API key tidak boleh kosong")
}
try {
// Mengambil data cuaca dari API
val response = api.getWeather(cityName, apiKey, "metric")
// Memastikan response valid dan memiliki data cuaca yang lengkap
val main = response?.main ?: throw IllegalStateException("Data cuaca utama tidak tersedia")
val wind = response.wind ?: throw IllegalStateException("Data kecepatan angin tidak tersedia")
// Membuat objek WeatherData berdasarkan data dari response API
val weatherData = WeatherData(
temp = main.temp,
humidity = main.humidity,
windSpeed = wind.speed,
pressure = main.pressure
)
// Menggunakan fungsi `predictWithModel` untuk mendapatkan rekomendasi dari model ML
val recommendation = try {
mlModel.predictWithModel(weatherData)
} catch (e: Exception) {
// Menangani kesalahan model ML dan memberikan rekomendasi default
"Tidak Terdefinisi"
}
// Mengembalikan hasil cuaca dengan rekomendasi cuaca berdasarkan model
WeatherResult(
city = response.name,
temp = weatherData.temp,
humidity = weatherData.humidity,
windSpeed = weatherData.windSpeed,
pressure = weatherData.pressure,
weatherCategory = recommendation
)
} catch (e: Exception) {
// Menangani kesalahan umum dan memberikan pesan kesalahan yang sesuai
throw WeatherRepositoryException("Gagal mendapatkan data cuaca: ${e.message}")
}!!
}
}
}
// Exception kustom untuk menangani kesalahan dalam repository
class WeatherRepositoryException(message: String) : Exception(message)
Penjelasan:
- fetchWeather: Mengambil data cuaca dari API dan memprosesnya dengan model ML untuk menghasilkan rekomendasi cuaca.
- KNN dan TensorFlow Lite: Model ML akan menerima data cuaca yang telah diproses dan menghasilkan rekomendasi cuaca untuk aktivitas luar ruangan.
7.16 WeatherMLModel.kt
Model ini menggabungkan KNN dan TensorFlow Lite untuk memprediksi rekomendasi cuaca.
package com.nandaadisaputra.weather.model
import android.content.Context
import com.nandaadisaputra.weather.network.WeatherService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.tensorflow.lite.Interpreter
import java.io.FileInputStream
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
import kotlin.math.pow
import kotlin.math.sqrt
class WeatherMLModel(context: Context) {
// Menggunakan lazy untuk menunda pemuatan model hingga diperlukan
private val model: Interpreter by lazy { Interpreter(loadModelFile(context)) }
// Memuat model dari file TensorFlow Lite dengan penanganan error
private fun loadModelFile(context: Context): MappedByteBuffer {
return try {
context.assets.openFd("weather_model.tflite").use { assetFileDescriptor ->
FileInputStream(assetFileDescriptor.fileDescriptor).use { fileInputStream ->
fileInputStream.channel.map(
FileChannel.MapMode.READ_ONLY,
assetFileDescriptor.startOffset,
assetFileDescriptor.declaredLength
)
}
}
} catch (e: Exception) {
// Mengembalikan exception dengan pesan yang jelas jika terjadi kesalahan
throw RuntimeException("Gagal memuat model cuaca: ${e.message}")
}
}
// Fungsi untuk menghitung jarak Euclidean antara dua data cuaca
private fun euclideanDistance(data1: WeatherData, data2: WeatherData): Float {
return sqrt(
((data1.temp - data2.temp).toDouble().pow(2) +
(data1.humidity - data2.humidity).toDouble().pow(2) +
(data1.windSpeed - data2.windSpeed).toDouble().pow(2) +
(data1.pressure - data2.pressure).toDouble().pow(2)).toFloat()
)
}
// Fungsi untuk memberikan rekomendasi cuaca berdasarkan KNN
private fun knnRecommendation(weatherData: WeatherData): String {
// Data cuaca historis untuk digunakan dalam KNN
val historicalWeatherData = listOf(
WeatherData(30f, 75, 10f, 1010f, "Cerah"),
WeatherData(25f, 80, 5f, 1020f, "Mendung"),
WeatherData(35f, 60, 15f, 1005f, "Hujan Ringan"),
WeatherData(28f, 70, 8f, 1015f, "Berawan"),
WeatherData(22f, 85, 3f, 1018f, "Hujan Deras"),
WeatherData(18f, 90, 12f, 1008f, "Angin Kencang"),
WeatherData(20f, 95, 4f, 1022f, "Kabut")
)
// Menemukan 3 tetangga terdekat berdasarkan jarak Euclidean
val nearestNeighbors = historicalWeatherData
.map { it to euclideanDistance(weatherData, it) }
.sortedBy { it.second } // Urutkan berdasarkan jarak terdekat
.take(3)
// Menghitung kategori cuaca yang paling sering muncul di antara tetangga terdekat
val weatherCategoryCount = nearestNeighbors.groupingBy { it.first.weatherCategory }
.eachCount()
// Mengembalikan kategori cuaca terbanyak, atau "Tidak Terdefinisi" jika tidak ada
return weatherCategoryCount.maxByOrNull { it.value }?.key ?: "Tidak Terdefinisi"
}
// Fungsi untuk mengambil data cuaca dari API dan memberikan rekomendasi
suspend fun predictRecommendation(city: String, apiKey: String): String {
return withContext(Dispatchers.IO) {
try {
// Mengambil data cuaca dari API
val response = WeatherService.create().getWeather(city, apiKey, "metric")
?: throw RuntimeException("Tidak ada respons dari API cuaca")
response.main?.let {
// Membuat objek WeatherData untuk prediksi
val weatherData = WeatherData(
temp = it.temp,
humidity = it.humidity,
windSpeed = response.wind.speed,
pressure = it.pressure
)
// Menggunakan metode KNN untuk rekomendasi cuaca
knnRecommendation(weatherData)
} ?: "Data cuaca tidak lengkap."
} catch (e: Exception) {
// Menangani error dan memberikan pesan yang jelas
"Gagal mendapatkan data cuaca: ${e.message}"
}
}
}
// Fungsi untuk melakukan prediksi cuaca menggunakan model TensorFlow Lite
fun predictWithModel(weatherData: WeatherData): String {
return try {
// Menyiapkan input untuk model (data cuaca)
val input = floatArrayOf(
weatherData.temp,
weatherData.humidity.toFloat(),
weatherData.windSpeed,
weatherData.pressure.toFloat()
)
// Menyiapkan output untuk model
val output = Array(1) { FloatArray(1) }
model.run(input, output)
// Mengembalikan kategori cuaca berdasarkan hasil output model
when (output[0][0].toInt()) {
0 -> "Cerah"
1 -> "Mendung"
2 -> "Hujan Ringan"
3 -> "Hujan Deras"
4 -> "Berawan"
5 -> "Angin Kencang"
6 -> "Kabut"
else -> "Tidak Terdefinisi"
}
} catch (e: Exception) {
// Menangani error dan memberikan pesan yang jelas
"Error dalam prediksi dengan model: ${e.message}"
}
}
}
Penjelasan:
- TensorFlow Lite: Digunakan untuk memprediksi rekomendasi cuaca berdasarkan input data cuaca yang diperoleh.
- Prediksi Cuaca: Model ML menghasilkan rekomendasi cuaca untuk aktivitas luar berdasarkan data input (suhu, kelembaban, tekanan, kecepatan angin).
7.17 WeatherViewModel.kt
ViewModel menghubungkan repository ke UI, memastikan data cuaca dan rekomendasi ditampilkan di layar.
package com.nandaadisaputra.weather.ui
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.nandaadisaputra.weather.model.WeatherMLModel
import com.nandaadisaputra.weather.network.WeatherResult
import com.nandaadisaputra.weather.repository.WeatherRepository
class WeatherViewModel(
private val weatherRepository: WeatherRepository,
private val weatherMLModel: WeatherMLModel
) : ViewModel() {
private val _weatherData = MutableLiveData<WeatherResult>()
val weatherData: LiveData<WeatherResult> get() = _weatherData
private val _weatherRecommendation = MutableLiveData<String>()
val weatherRecommendation: LiveData<String> get() = _weatherRecommendation
private val _error = MutableLiveData<String>()
val error: LiveData<String> get() = _error
suspend fun fetchWeatherWithRecommendation(city: String, apiKey: String) {
try {
// Mendapatkan data cuaca dengan rekomendasi
val weatherResult = weatherRepository.fetchWeather(city, apiKey)
// Update LiveData dengan data cuaca
_weatherData.postValue(weatherResult)
// Mengambil rekomendasi cuaca dari model ML dan memperbarui LiveData
val recommendation = fetchRecommendation(city, apiKey)
_weatherRecommendation.postValue(recommendation)
} catch (e: Exception) {
// Menangani error jika terjadi masalah saat mengambil data
_error.postValue("Error fetching weather data: ${e.message}")
}
}
// Fungsi untuk mendapatkan rekomendasi cuaca dari model ML
suspend fun fetchRecommendation(city: String, apiKey: String): String {
return weatherMLModel.predictRecommendation(city, apiKey)
}
}
Penjelasan:
- LiveData: Mengamati perubahan data cuaca dan rekomendasi untuk ditampilkan ke UI.
- fetchWeather: Mengambil data cuaca dari repository dan mengirimkan data ke UI untuk ditampilkan.
7.18 WeatherViewModelFactory.kt
ViewModelFactory untuk memastikan bahwa ViewModel diinisialisasi dengan benar dengan dependensi yang dibutuhkan.
package com.nandaadisaputra.weather.helper
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.nandaadisaputra.weather.model.WeatherMLModel
import com.nandaadisaputra.weather.repository.WeatherRepository
import com.nandaadisaputra.weather.ui.WeatherViewModel
class WeatherViewModelFactory(
private val repository: WeatherRepository,
private val mlModel: WeatherMLModel
) : ViewModelProvider.Factory {
// Fungsi untuk membuat instance dari WeatherViewModel
override fun <T : ViewModel> create(modelClass: Class<T>): T {
// Mengecek apakah kelas ViewModel yang diminta adalah WeatherViewModel
return when {
modelClass.isAssignableFrom(WeatherViewModel::class.java) -> {
WeatherViewModel(repository, mlModel) as T // Mengembalikan instance WeatherViewModel
}
else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
}
}
}
Penjelasan:
- ViewModelFactory: Membuat instance
WeatherViewModel
dengan dependency yang benar, dalam hal iniWeatherRepository
.
Hasil yang Diharapkan
✅ Menguasai Dasar AI Prediktif dalam Cuaca
Membuka wawasan Anda tentang kecerdasan buatan yang digunakan untuk meramal cuaca dengan akurasi.
✅ Mengambil Data Cuaca dari API dengan Akurasi Tinggi
Mempelajari cara mengambil data cuaca dengan presisi, memungkinkan aplikasi Anda memberikan informasi yang akurat.
✅ Membangun Model AI dengan TensorFlow Lite
Mengetahui cara mengembangkan model AI yang ringan dan efektif untuk perangkat Android dengan menggunakan TensorFlow Lite.
✅ Mengembangkan Aplikasi Cuaca Berbasis AI di Android Studio
Membuat aplikasi cuaca yang responsif dan berkualitas tinggi dengan integrasi AI, memberikan pengalaman pengguna yang mulus.
✅ Prediksi Cuaca Real-Time
Aplikasi Anda akan dapat memprediksi cuaca secara real-time berdasarkan input parameter suhu, kelembaban, dan tekanan udara.
Semoga tutorial ini memberikan wawasan baru dan menginspirasi Anda dalam mengembangkan aplikasi berbasis AI. 🚀
Jika Anda ingin melihat proyek lengkapnya, kunjungi https://github.com/NandaAdisaputra/Weather
Ada pertanyaan atau ingin berdiskusi lebih lanjut? Jangan ragu untuk menghubungi saya di Instagram @nanda_coding_android.