diff --git a/lib/pages/analytics/models/analytics_device.dart b/lib/pages/analytics/models/analytics_device.dart index 1b5f0ae0..6f066407 100644 --- a/lib/pages/analytics/models/analytics_device.dart +++ b/lib/pages/analytics/models/analytics_device.dart @@ -1,11 +1,13 @@ class AnalyticsDevice { - const AnalyticsDevice(this.uuid); + const AnalyticsDevice({required this.name, required this.uuid}); final String uuid; + final String name; factory AnalyticsDevice.fromJson(Map json) { return AnalyticsDevice( - json['uuid'] as String? ?? '', + uuid: json['uuid'] as String? ?? '', + name: json['name'] as String? ?? '', ); } } diff --git a/lib/pages/analytics/modules/analytics/views/analytics_page.dart b/lib/pages/analytics/modules/analytics/views/analytics_page.dart index 5c801c93..dc8457a5 100644 --- a/lib/pages/analytics/modules/analytics/views/analytics_page.dart +++ b/lib/pages/analytics/modules/analytics/views/analytics_page.dart @@ -12,7 +12,9 @@ import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/real import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy/occupancy_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy_heat_map/occupancy_heat_map_bloc.dart'; -import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_analytics_devices_service.dart'; +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/energy_consumption_by_phases/fake_energy_consumption_by_phases_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/fake_energy_consumption_per_device_service.dart'; import 'package:syncrow_web/pages/analytics/services/occupacy/fake_occupacy_service.dart'; @@ -82,7 +84,10 @@ class _AnalyticsPageState extends State { BlocProvider(create: (context) => AnalyticsDatePickerBloc()), BlocProvider( create: (context) => AnalyticsDevicesBloc( - RemoteAnalyticsDevicesService(_httpService), + AnalyticsDevicesServiceDelegate( + RemoteOccupancyAnalyticsDevicesService(_httpService), + RemoteEnergyManagementAnalyticsDevicesService(_httpService), + ), ), ), ], diff --git a/lib/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart b/lib/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart index f8ff0627..b853a8b0 100644 --- a/lib/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart +++ b/lib/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart @@ -111,7 +111,8 @@ abstract final class FetchEnergyManagementDataHelper { GetAnalyticsDevicesParam( communityUuid: communityUuid, spaceUuid: spaceUuid, - deviceType: 'PC', + deviceTypes: ['PC'], + requestType: AnalyticsDeviceRequestType.energyManagement, ), ), ); diff --git a/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart b/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart index 403a752d..fb9ff34a 100644 --- a/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart +++ b/lib/pages/analytics/modules/occupancy/helpers/fetch_occupancy_data_helper.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/analytics_date_picker_bloc/analytics_date_picker_bloc.dart'; +import 'package:syncrow_web/pages/analytics/modules/analytics/blocs/analytics_devices/analytics_devices_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/realtime_device_changes/realtime_device_changes_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy/occupancy_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/occupancy/blocs/occupancy_heat_map/occupancy_heat_map_bloc.dart'; +import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_heat_map_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_occupancy_param.dart'; @@ -21,6 +24,9 @@ abstract final class FetchOccupancyDataHelper { final datePickerState = context.read().state; + loadAnalyticsDevices(context, communityUuid: communityId, spaceUuid: spaceId); + final selectedDevice = context.read().state.selectedDevice; + context.read().add( LoadOccupancyEvent( GetOccupancyParam( @@ -41,11 +47,30 @@ abstract final class FetchOccupancyDataHelper { ), ); - context.read() - ..add(const RealtimeDeviceChangesClosed()) - ..add( - const RealtimeDeviceChangesStarted('14fe6e7e-47af-4a07-ae0a-7c4a26ef8135'), - ); + if (selectedDevice case final AnalyticsDevice device) { + context.read() + ..add(const RealtimeDeviceChangesClosed()) + ..add( + RealtimeDeviceChangesStarted(device.uuid), + ); + } + } + + static void loadAnalyticsDevices( + BuildContext context, { + required String communityUuid, + required String spaceUuid, + }) { + context.read().add( + LoadAnalyticsDevicesEvent( + GetAnalyticsDevicesParam( + communityUuid: communityUuid, + spaceUuid: spaceUuid, + deviceTypes: ['WPS', 'CPS'], + requestType: AnalyticsDeviceRequestType.occupancy, + ), + ), + ); } static void clearAllData(BuildContext context) { @@ -58,5 +83,9 @@ abstract final class FetchOccupancyDataHelper { context.read().add( const RealtimeDeviceChangesClosed(), ); + + context.read().add( + const ClearAnalyticsDeviceEvent(), + ); } } diff --git a/lib/pages/analytics/params/get_analytics_devices_param.dart b/lib/pages/analytics/params/get_analytics_devices_param.dart index 2efcad0f..f8f4e526 100644 --- a/lib/pages/analytics/params/get_analytics_devices_param.dart +++ b/lib/pages/analytics/params/get_analytics_devices_param.dart @@ -1,17 +1,20 @@ +enum AnalyticsDeviceRequestType { energyManagement, occupancy } + class GetAnalyticsDevicesParam { final String? spaceUuid; - final String deviceType; + final List deviceTypes; final String? communityUuid; + final AnalyticsDeviceRequestType requestType; const GetAnalyticsDevicesParam({ + required this.requestType, required this.spaceUuid, - required this.deviceType, + required this.deviceTypes, required this.communityUuid, }); Map toJson() { return { - 'deviceType': deviceType, if (spaceUuid != null) 'spaceUuid': spaceUuid, if (communityUuid != null) 'communityUuid': communityUuid, }; diff --git a/lib/pages/analytics/services/analytics_devices/analytics_devices_service_delagate.dart b/lib/pages/analytics/services/analytics_devices/analytics_devices_service_delagate.dart new file mode 100644 index 00000000..2d735df6 --- /dev/null +++ b/lib/pages/analytics/services/analytics_devices/analytics_devices_service_delagate.dart @@ -0,0 +1,24 @@ +import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; +import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; +import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; + +class AnalyticsDevicesServiceDelegate implements AnalyticsDevicesService { + const AnalyticsDevicesServiceDelegate( + this._occupancyService, + this._energyManagementService, + ); + + final AnalyticsDevicesService _occupancyService; + final AnalyticsDevicesService _energyManagementService; + + @override + Future> getDevices( + GetAnalyticsDevicesParam param, + ) { + return switch (param.requestType) { + AnalyticsDeviceRequestType.occupancy => _occupancyService.getDevices(param), + AnalyticsDeviceRequestType.energyManagement => + _energyManagementService.getDevices(param), + }; + } +} diff --git a/lib/pages/analytics/services/analytics_devices/remote_analytics_devices_service.dart b/lib/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart similarity index 69% rename from lib/pages/analytics/services/analytics_devices/remote_analytics_devices_service.dart rename to lib/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart index a8439d65..adf8a6fa 100644 --- a/lib/pages/analytics/services/analytics_devices/remote_analytics_devices_service.dart +++ b/lib/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart @@ -3,8 +3,9 @@ import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.d import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; import 'package:syncrow_web/services/api/http_service.dart'; -final class RemoteAnalyticsDevicesService implements AnalyticsDevicesService { - const RemoteAnalyticsDevicesService(this._httpService); +final class RemoteEnergyManagementAnalyticsDevicesService + implements AnalyticsDevicesService { + const RemoteEnergyManagementAnalyticsDevicesService(this._httpService); final HTTPService _httpService; @@ -12,8 +13,9 @@ final class RemoteAnalyticsDevicesService implements AnalyticsDevicesService { Future> getDevices(GetAnalyticsDevicesParam param) async { try { final response = await _httpService.get( - path: '/devices/recursive-child', - queryParameters: param.toJson(), + path: '/devices-space-community/recursive-child', + queryParameters: param.toJson() + ..addAll({'productType': param.deviceTypes.first}), expectedResponseModel: (response) { final json = response as Map; final dailyData = json['data'] as List? ?? []; @@ -28,7 +30,7 @@ final class RemoteAnalyticsDevicesService implements AnalyticsDevicesService { return response; } catch (e) { - throw Exception('Failed to load total energy consumption:'); + throw Exception('Failed to load total energy consumption: $e'); } } } diff --git a/lib/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart b/lib/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart new file mode 100644 index 00000000..95a4aacf --- /dev/null +++ b/lib/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart @@ -0,0 +1,62 @@ +import 'package:syncrow_web/pages/analytics/models/analytics_device.dart'; +import 'package:syncrow_web/pages/analytics/params/get_analytics_devices_param.dart'; +import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics_devices_service.dart'; +import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; +import 'package:syncrow_web/services/api/http_service.dart'; + +class RemoteOccupancyAnalyticsDevicesService implements AnalyticsDevicesService { + const RemoteOccupancyAnalyticsDevicesService(this._httpService); + + final HTTPService _httpService; + + @override + Future> getDevices(GetAnalyticsDevicesParam param) async { + try { + final requests = await Future.wait>( + param.deviceTypes.map((e) { + final mappedParam = GetAnalyticsDevicesParam( + requestType: AnalyticsDeviceRequestType.occupancy, + spaceUuid: param.spaceUuid, + deviceTypes: [e], + communityUuid: param.communityUuid, + ); + return _makeRequest(mappedParam); + }).toList(), + ); + + final result = requests.map((e) => e.first).toList(); + return result; + } catch (e) { + throw Exception('Failed to load total energy consumption: $e'); + } + } + + Future> _makeRequest(GetAnalyticsDevicesParam param) async { + try { + final projectUuid = await ProjectManager.getProjectUUID(); + + final response = await _httpService.get( + path: + '/projects/$projectUuid/communities/${param.communityUuid}/spaces/${param.spaceUuid}/devices', + queryParameters: { + 'requestType': param.requestType.name, + 'communityUuid': param.communityUuid, + 'spaceUuid': param.spaceUuid, + 'productType': param.deviceTypes.first, + }, + expectedResponseModel: (response) { + final json = response as Map; + final dailyData = json['data'] as List? ?? []; + + final result = dailyData.map( + (json) => AnalyticsDevice.fromJson(json as Map), + ); + return result.toList(); + }, + ); + return response; + } catch (e) { + rethrow; + } + } +}