Integrated realtime data.

This commit is contained in:
Faris Armoush
2025-05-05 16:58:48 +03:00
parent 4d5de7bc05
commit 38184ca8b2
8 changed files with 70 additions and 18 deletions

View File

@ -6,10 +6,12 @@ import 'package:syncrow_web/pages/analytics/modules/analytics/widgets/analytics_
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_by_phases/energy_consumption_by_phases_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_per_device/energy_consumption_per_device_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/power_clamp_info/power_clamp_info_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/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.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/power_clamp_info/remote_power_clamp_info_service.dart';
import 'package:syncrow_web/pages/analytics/services/realtime_device_service/firebase_realtime_device_service.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/fake_total_energy_consumption_service.dart';
import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart';
import 'package:syncrow_web/services/api/http_service.dart';
@ -46,6 +48,11 @@ class AnalyticsPage extends StatelessWidget {
RemotePowerClampInfoService(HTTPService()),
),
),
BlocProvider(
create: (context) => RealtimeDeviceChangesBloc(
FirebaseRealtimeDeviceService(),
),
),
],
child: const AnalyticsPageForm(),
);

View File

@ -43,5 +43,13 @@ class PowerClampInfoBloc extends Bloc<PowerClampInfoEvent, PowerClampInfoState>
void _onUpdatePowerClampStatusEvent(
UpdatePowerClampStatusEvent event,
Emitter<PowerClampInfoState> emit,
) async {}
) async {
final currentModel = state.powerClampModel;
if (currentModel == null) return;
final updatedStatus = PowerStatus.fromStatusList(event.statusList);
final updatedModel = currentModel.copyWith(statusPower: updatedStatus);
emit(state.copyWith(powerClampModel: updatedModel));
}
}

View File

@ -25,8 +25,12 @@ class RealtimeDeviceChangesBloc
onData: (data) {
final currentState = state;
emit(
state.copyWith(
deviceStatusList: [...currentState.deviceStatusList, data],
state.copyWith(
deviceStatusList: [
...currentState.deviceStatusList.where((device) =>
!data.any((newDevice) => newDevice.code == device.code)),
...data,
],
),
);
},

View File

@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_by_phases/energy_consumption_by_phases_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_per_device/energy_consumption_per_device_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/power_clamp_info/power_clamp_info_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/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart_box.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/power_clamp_energy_data_widget.dart';
@ -28,6 +29,12 @@ class _AnalyticsEnergyManagementViewState
_loadTotalEnergyConsumption();
_loadEnergyConsumptionPerDevice();
_loadPowerClampInfo();
context.read<RealtimeDeviceChangesBloc>().add(
const RealtimeDeviceChangesStarted(
'cb71d6ad-6e29-4eaa-ae3e-1a0d1c5f60fa',
),
);
super.initState();
}

View File

@ -19,9 +19,11 @@ class PowerClampEnergyDataWidget extends StatelessWidget {
Widget build(BuildContext context) {
return BlocListener<RealtimeDeviceChangesBloc, RealtimeDeviceChangesState>(
listener: (context, state) {
context.read<PowerClampInfoBloc>().add(
UpdatePowerClampStatusEvent(state.deviceStatusList),
);
if (state.status != RealtimeDeviceChangesStatus.loaded) {
context.read<PowerClampInfoBloc>().add(
UpdatePowerClampStatusEvent(state.deviceStatusList),
);
}
},
child: BlocBuilder<PowerClampInfoBloc, PowerClampInfoState>(
builder: (context, state) {

View File

@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/device_sta
class FirebaseRealtimeDeviceService implements RealtimeDeviceService {
@override
Stream<Status> subscribe(String deviceId) {
Stream<List<Status>> subscribe(String deviceId) {
try {
final ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
@ -15,11 +15,17 @@ class FirebaseRealtimeDeviceService implements RealtimeDeviceService {
throw Exception('Invalid data received from Firebase');
}
final statusMap = data['status'] as Map<dynamic, dynamic>;
return Status(
code: statusMap['code'] as String? ?? '',
value: statusMap['value'] as String? ?? '',
);
final statusMap = data['status'] as List<dynamic>;
return statusMap.map((dynamic status) {
if (status is! Map<dynamic, dynamic>) {
throw Exception('Invalid status format');
}
return Status(
code: status['code']?.toString() ?? '',
value: num.tryParse(status['value']?.toString() ?? '0') ,
);
}).toList();
});
} catch (e) {
throw Exception('Error subscribing to device status: $e');

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
abstract interface class RealtimeDeviceService {
Stream<Status> subscribe(String deviceId);
Stream<List<Status>> subscribe(String deviceId);
}

View File

@ -1,4 +1,6 @@
// PowerClampModel class to represent the response
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
class PowerClampModel {
String productUuid;
String productType;
@ -46,11 +48,27 @@ class PowerStatus {
factory PowerStatus.fromJson(Map<String, dynamic> json) {
return PowerStatus(
phaseA: Phase.fromJson(json['phaseA']as List<dynamic>? ?? []),
phaseB: Phase.fromJson(json['phaseB']as List<dynamic>? ?? []),
phaseC: Phase.fromJson(json['phaseC']as List<dynamic>? ?? []),
general: Phase.fromJson(json['general']as List<dynamic>? ?? []
));
phaseA: Phase.fromJson(json['phaseA'] as List<dynamic>? ?? []),
phaseB: Phase.fromJson(json['phaseB'] as List<dynamic>? ?? []),
phaseC: Phase.fromJson(json['phaseC'] as List<dynamic>? ?? []),
general: Phase.fromJson(json['general'] as List<dynamic>? ?? []),
);
}
factory PowerStatus.fromStatusList(List<Status> statuses) {
List<DataPoint> extractPhase(String prefix) {
return statuses
.where((s) => s.code.endsWith(prefix))
.map((s) => DataPoint(code: s.code, value: s.value))
.toList();
}
return PowerStatus(
phaseA: Phase(dataPoints: extractPhase('A')),
phaseB: Phase(dataPoints: extractPhase('B')),
phaseC: Phase(dataPoints: extractPhase('C')),
general: Phase(dataPoints: extractPhase('')),
);
}
}