import 'package:dio/dio.dart'; import '../core/api_config.dart'; /// Layanan Klien untuk mengirimkan instruksi kontrol hardware (ESP32) ke API Backend. /// Menangani pemanggilan REST API untuk: pengaturan mode (Auto/Manual), threshold, penyiraman manual, dan penjadwalan. class ApiControlService { final Dio _dio; final String deviceId; ApiControlService(this.deviceId, [Dio? dio]) : _dio = dio ?? Dio(); // ── Mode Operasi ───────────────────────────────────────────── /// Mengambil mode operasi perangkat saat ini dari backend. Future getMode() async { try { final res = await _dio.get('${ApiConfig.baseUrl}/mode/$deviceId'); if (res.statusCode == 200 && res.data != null) { return res.data['current_mode'] ?? 'auto'; } return 'auto'; } catch (e) { return 'auto'; } } /// Mengubah mode operasi perangkat (Otomatis/Manual) di server. Future setMode(String mode) async { try { await _dio.post( '${ApiConfig.baseUrl}/mode/$deviceId', data: {'mode': mode}, ); } catch (e) { throw Exception('Gagal mengubah mode: $e'); } } /// Mengambil nilai batas threshold sensor suhu dan kelembapan saat ini. Future> getThreshold() async { try { final res = await _dio.get('${ApiConfig.baseUrl}/threshold/$deviceId'); if (res.statusCode == 200 && res.data != null) { return res.data; } throw Exception('Gagal memuat threshold'); } catch (e) { throw Exception('Error: $e'); } } /// Memperbarui nilai batas threshold suhu ([tempMax]) dan kelembapan ([humMax]) di server. Future updateThreshold(double tempMax, double humMax) async { try { await _dio.post( '${ApiConfig.baseUrl}/threshold/$deviceId', data: { 'temp_max': tempMax, 'hum_max': humMax, }, ); } catch (e) { throw Exception('Gagal update threshold: $e'); } } // ── Manual Control (Pompa) ─────────────────────────────────── /// Mengirimkan instruksi menyalakan pompa secara instan selama [durationSeconds] detik. Future siramManual(int durationSeconds) async { try { await _dio.post( '${ApiConfig.baseUrl}/schedule/$deviceId/now', data: {'duration_s': durationSeconds}, ); } catch (e) { throw Exception('Gagal menyalakan pompa: $e'); } } /// Menghentikan aktivitas pompa secara instan (mematikan pompa). Future stopPump() async { try { await _dio.post('${ApiConfig.baseUrl}/schedule/$deviceId/stop'); } catch (e) { throw Exception('Gagal mematikan pompa: $e'); } } // ── Schedules (Jadwal) ─────────────────────────────────────── /// Mengambil daftar semua jadwal penyiraman otomatis yang terdaftar untuk perangkat ini. Future> getSchedules() async { try { final res = await _dio.get('${ApiConfig.baseUrl}/schedule/$deviceId'); if (res.statusCode == 200 && res.data != null) { return res.data as List; } return []; } catch (e) { throw Exception('Gagal memuat jadwal: $e'); } } /// Menambahkan jadwal penyiraman baru ke backend. /// [cron] format string cron UTC, [durationSeconds] durasi siram, [label] penanda nama jadwal. Future> addSchedule(String cron, int durationSeconds, String label) async { try { final res = await _dio.post( '${ApiConfig.baseUrl}/schedule/$deviceId', data: { 'cron': cron, 'duration_s': durationSeconds, 'label': label, }, ); if (res.statusCode == 200 || res.statusCode == 201) { return res.data; } throw Exception('Gagal menambah jadwal'); } catch (e) { throw Exception('Error tambah jadwal: $e'); } } /// Menghapus jadwal tertentu berdasarkan ID. Future deleteSchedule(String id) async { try { await _dio.delete('${ApiConfig.baseUrl}/schedule/$id'); } catch (e) { throw Exception('Gagal menghapus jadwal: $e'); } } /// Mengaktifkan atau menonaktifkan saklar jadwal tertentu (toggle status is_active). Future toggleSchedule(String id) async { try { await _dio.patch('${ApiConfig.baseUrl}/schedule/$id/toggle'); } catch (e) { throw Exception('Gagal toggle jadwal: $e'); } } }