class SensorModel { final double temperature; final double humidity; final double co2; final double pm25; final String temperatureStatus; final String humidityStatus; final String co2Status; final String pm25Status; final String overallStatus; final bool acPower; final String acMode; final int acTemp; final String acFan; final String timestamp; SensorModel({ required this.temperature, required this.humidity, required this.co2, required this.pm25, required this.temperatureStatus, required this.humidityStatus, required this.co2Status, required this.pm25Status, required this.overallStatus, required this.acPower, required this.acMode, required this.acTemp, required this.acFan, required this.timestamp, }); factory SensorModel.fromMap(Map json) { return SensorModel( // Support both ESP32 field names (suhu, kelembapan) and Flutter field names temperature: ((json['temperature'] ?? json['suhu']) ?? 0).toDouble(), humidity: ((json['humidity'] ?? json['kelembapan']) ?? 0).toDouble(), co2: ((json['co2'] ?? json['co2_ppm']) ?? 0).toDouble(), pm25: ((json['pm25'] ?? json['pm25_ugm3']) ?? 0).toDouble(), temperatureStatus: (json['temperature_status'] ?? json['suhu_status'] ?? ''), humidityStatus: (json['humidity_status'] ?? json['kelembapan_status'] ?? ''), co2Status: (json['co2_status'] ?? json['co2_status'] ?? ''), pm25Status: (json['pm25_status'] ?? json['pm25_status'] ?? ''), overallStatus: (json['overall_status'] ?? json['status_keseluruhan'] ?? ''), acPower: json['ac_power'] ?? false, acMode: json['ac_mode'] ?? 'OFF', acTemp: json['ac_temp'] ?? 24, acFan: json['ac_fan'] ?? 'AUTO', timestamp: _parseTimestamp(json['timestamp'] ?? json['last_update']), ); } Map toMap() { return { 'temperature': temperature, 'humidity': humidity, 'co2': co2, 'pm25': pm25, 'temperature_status': temperatureStatus, 'humidity_status': humidityStatus, 'co2_status': co2Status, 'pm25_status': pm25Status, 'overall_status': overallStatus, 'ac_power': acPower, 'ac_mode': acMode, 'ac_temp': acTemp, 'ac_fan': acFan, 'timestamp': timestamp, }; } } String _parseTimestamp(dynamic value) { if (value == null) return ''; if (value is int) { // ESP32 mengirim unix timestamp dalam detik, konversi ke milliseconds // Jika value > 10000000000 berarti sudah dalam milliseconds final timestampMs = value > 10000000000 ? value : value * 1000; final dt = DateTime.fromMillisecondsSinceEpoch(timestampMs); return "${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} " "${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}:${dt.second.toString().padLeft(2, '0')}"; } return value.toString(); }