From 24a7f3ac2a2f214eefaf32c1800591d7e8bfd557 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Wed, 4 Jun 2025 13:06:27 +0300 Subject: [PATCH] SP-1594-device-location-api-integration. --- .../analytics/models/analytics_device.dart | 6 +++ .../models/device_location_info.dart | 5 +-- .../fetch_air_quality_data_helper.dart | 8 ++-- .../analytics/views/analytics_page.dart | 10 ++++- ...ce_location_details_service_decorator.dart | 40 +++++++++++++++++++ .../remote_device_location_service.dart | 7 +++- ...ode_device_location_service_decorator.dart | 40 ------------------- 7 files changed, 65 insertions(+), 51 deletions(-) create mode 100644 lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart delete mode 100644 lib/pages/analytics/services/device_location/reverse_geocode_device_location_service_decorator.dart diff --git a/lib/pages/analytics/models/analytics_device.dart b/lib/pages/analytics/models/analytics_device.dart index eaac8b2b..3340a41d 100644 --- a/lib/pages/analytics/models/analytics_device.dart +++ b/lib/pages/analytics/models/analytics_device.dart @@ -8,6 +8,8 @@ class AnalyticsDevice { this.isActive, this.productDevice, this.spaceUuid, + this.latitude, + this.longitude, }); final String uuid; @@ -18,6 +20,8 @@ class AnalyticsDevice { final bool? isActive; final ProductDevice? productDevice; final String? spaceUuid; + final double? latitude; + final double? longitude; factory AnalyticsDevice.fromJson(Map json) { return AnalyticsDevice( @@ -35,6 +39,8 @@ class AnalyticsDevice { ? ProductDevice.fromJson(json['productDevice'] as Map) : null, spaceUuid: json['spaceUuid'] as String?, + latitude: json['lat'] != null ? double.parse(json['lat'] as String) : null, + longitude: json['lon'] != null ? double.parse(json['lon'] as String) : null, ); } } diff --git a/lib/pages/analytics/models/device_location_info.dart b/lib/pages/analytics/models/device_location_info.dart index 9b0095f7..aef7eebb 100644 --- a/lib/pages/analytics/models/device_location_info.dart +++ b/lib/pages/analytics/models/device_location_info.dart @@ -19,11 +19,8 @@ class DeviceLocationInfo extends Equatable { factory DeviceLocationInfo.fromJson(Map json) { return DeviceLocationInfo( - airQuality: json['airQuality'] as double?, + airQuality: json['aqi'] as double?, humidity: json['humidity'] as double?, - city: json['city'] as String?, - country: json['country'] as String?, - address: json['address'] as String?, temperature: json['temperature'] as double?, ); } diff --git a/lib/pages/analytics/modules/air_quality/helpers/fetch_air_quality_data_helper.dart b/lib/pages/analytics/modules/air_quality/helpers/fetch_air_quality_data_helper.dart index 7f26bb5a..cb37484c 100644 --- a/lib/pages/analytics/modules/air_quality/helpers/fetch_air_quality_data_helper.dart +++ b/lib/pages/analytics/modules/air_quality/helpers/fetch_air_quality_data_helper.dart @@ -65,7 +65,7 @@ abstract final class FetchAirQualityDataHelper { communityUuid: communityUuid, spaceUuid: spaceUuid, deviceTypes: ['AQI'], - requestType: AnalyticsDeviceRequestType.energyManagement, + requestType: AnalyticsDeviceRequestType.occupancy, ), onSuccess: (device) { context.read() @@ -73,10 +73,10 @@ abstract final class FetchAirQualityDataHelper { ..add(RealtimeDeviceChangesStarted(device.uuid)); context.read().add( - const LoadDeviceLocationEvent( + LoadDeviceLocationEvent( GetDeviceLocationDataParam( - latitude: 35.6895, - longitude: 139.6917, + latitude: device.latitude ?? 0, + longitude: device.longitude ?? 0, ), ), ); diff --git a/lib/pages/analytics/modules/analytics/views/analytics_page.dart b/lib/pages/analytics/modules/analytics/views/analytics_page.dart index 01dc8ef5..1ecd9aa3 100644 --- a/lib/pages/analytics/modules/analytics/views/analytics_page.dart +++ b/lib/pages/analytics/modules/analytics/views/analytics_page.dart @@ -1,3 +1,4 @@ +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart'; @@ -19,8 +20,8 @@ import 'package:syncrow_web/pages/analytics/services/air_quality_distribution/fa import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service_delagate.dart'; import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart'; import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart'; +import 'package:syncrow_web/pages/analytics/services/device_location/device_location_details_service_decorator.dart'; import 'package:syncrow_web/pages/analytics/services/device_location/remote_device_location_service.dart'; -import 'package:syncrow_web/pages/analytics/services/device_location/reverse_geocode_device_location_service_decorator.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/remote_energy_consumption_by_phases_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/remote_energy_consumption_per_device_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupacy/remote_occupancy_service.dart'; @@ -113,8 +114,13 @@ class _AnalyticsPageState extends State { ), BlocProvider( create: (context) => DeviceLocationBloc( - ReverseGeocodeDeviceLocationServiceDecorator( + DeviceLocationDetailsServiceDecorator( RemoteDeviceLocationService(_httpService), + Dio( + BaseOptions( + baseUrl: 'https://nominatim.openstreetmap.org/', + ), + ), ), ), ), diff --git a/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart b/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart new file mode 100644 index 00000000..0239bcb7 --- /dev/null +++ b/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart @@ -0,0 +1,40 @@ +import 'package:dio/dio.dart'; +import 'package:syncrow_web/pages/analytics/models/device_location_info.dart'; +import 'package:syncrow_web/pages/analytics/params/get_device_location_data_param.dart'; +import 'package:syncrow_web/pages/analytics/services/device_location/device_location_service.dart'; + +class DeviceLocationDetailsServiceDecorator implements DeviceLocationService { + const DeviceLocationDetailsServiceDecorator(this._decoratee, this._dio); + + final DeviceLocationService _decoratee; + final Dio _dio; + + @override + Future get(GetDeviceLocationDataParam param) async { + try { + final deviceLocationInfo = await _decoratee.get(param); + final response = await _dio.get>( + 'reverse', + queryParameters: { + 'format': 'json', + 'lat': param.latitude, + 'lon': param.longitude, + }, + ); + + final data = response.data; + if (data != null) { + final addressData = data['address'] as Map; + return deviceLocationInfo.copyWith( + city: addressData['city'], + country: addressData['country_code'].toString().toUpperCase(), + address: addressData['state'], + ); + } + + return deviceLocationInfo; + } catch (e) { + throw Exception('Failed to load device location info: ${e.toString()}'); + } + } +} diff --git a/lib/pages/analytics/services/device_location/remote_device_location_service.dart b/lib/pages/analytics/services/device_location/remote_device_location_service.dart index dce547a2..b8820180 100644 --- a/lib/pages/analytics/services/device_location/remote_device_location_service.dart +++ b/lib/pages/analytics/services/device_location/remote_device_location_service.dart @@ -17,7 +17,12 @@ class RemoteDeviceLocationService implements DeviceLocationService { final response = await _httpService.get( path: '/weather', queryParameters: param.toJson(), - expectedResponseModel: (data) => DeviceLocationInfo.fromJson(data), + expectedResponseModel: (data) { + final response = data as Map; + final location = response['data'] as Map; + + return DeviceLocationInfo.fromJson(location); + }, ); return response; } on DioException catch (e) { diff --git a/lib/pages/analytics/services/device_location/reverse_geocode_device_location_service_decorator.dart b/lib/pages/analytics/services/device_location/reverse_geocode_device_location_service_decorator.dart deleted file mode 100644 index a3ac1e55..00000000 --- a/lib/pages/analytics/services/device_location/reverse_geocode_device_location_service_decorator.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:geocoding/geocoding.dart'; -import 'package:syncrow_web/pages/analytics/models/device_location_info.dart'; -import 'package:syncrow_web/pages/analytics/params/get_device_location_data_param.dart'; -import 'package:syncrow_web/pages/analytics/services/device_location/device_location_service.dart'; - -class ReverseGeocodeDeviceLocationServiceDecorator implements DeviceLocationService { - const ReverseGeocodeDeviceLocationServiceDecorator(this._decoratee); - - final DeviceLocationService _decoratee; - - @override - Future get(GetDeviceLocationDataParam param) async { - try { - final deviceLocationInfo = await _decoratee.get(param); - - final placemarks = await placemarkFromCoordinates( - param.latitude, - param.longitude, - ); - - if (placemarks.isNotEmpty) { - final place = placemarks.first; - - final city = place.locality; - final country = place.country; - final address = place.street; - - return deviceLocationInfo.copyWith( - city: city, - country: country, - address: address, - ); - } - - return deviceLocationInfo; - } catch (e) { - throw Exception('Failed to reverse load device location info'); - } - } -}