mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Merge branch 'dev' of https://github.com/SyncrowIOT/web into dev
This commit is contained in:
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
|
||||||
|
|
||||||
class SearchResetButtons extends StatelessWidget {
|
class SearchResetButtons extends StatelessWidget {
|
||||||
const SearchResetButtons({
|
const SearchResetButtons({
|
||||||
@ -17,8 +17,10 @@ class SearchResetButtons extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 25),
|
const SizedBox(height: 25),
|
||||||
|
@ -72,6 +72,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
|
|||||||
child: state is DeviceManagementLoading
|
child: state is DeviceManagementLoading
|
||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: Column(
|
: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: isLargeScreenSize(context)
|
padding: isLargeScreenSize(context)
|
||||||
|
@ -14,29 +14,29 @@ class DeviceSearchFilters extends StatefulWidget {
|
|||||||
|
|
||||||
class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
class _DeviceSearchFiltersState extends State<DeviceSearchFilters>
|
||||||
with HelperResponsiveLayout {
|
with HelperResponsiveLayout {
|
||||||
final _unitNameController = TextEditingController();
|
late final TextEditingController _unitNameController;
|
||||||
final _productNameController = TextEditingController();
|
late final TextEditingController _productNameController;
|
||||||
|
|
||||||
List<Widget> get _widgets => [
|
@override
|
||||||
_buildSearchField("Space Name", _unitNameController, 200),
|
void initState() {
|
||||||
_buildSearchField("Device Name / Product Name", _productNameController, 300),
|
_unitNameController = TextEditingController();
|
||||||
_buildSearchResetButtons(),
|
_productNameController = TextEditingController();
|
||||||
];
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (isExtraLargeScreenSize(context)) {
|
|
||||||
return Row(
|
|
||||||
children: _widgets
|
|
||||||
.map((e) => Padding(padding: const EdgeInsets.all(10), child: e))
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Wrap(
|
return Wrap(
|
||||||
|
alignment: WrapAlignment.start,
|
||||||
|
runAlignment: WrapAlignment.start,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
runSpacing: 10,
|
runSpacing: 10,
|
||||||
children: _widgets,
|
children: [
|
||||||
|
_buildSearchField("Space Name", _unitNameController, 200),
|
||||||
|
_buildSearchField("Device Name / Product Name", _productNameController, 300),
|
||||||
|
_buildSearchResetButtons(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,10 @@ class FlushMountedPresenceSensorChangeValueEvent
|
|||||||
extends FlushMountedPresenceSensorEvent {
|
extends FlushMountedPresenceSensorEvent {
|
||||||
final int value;
|
final int value;
|
||||||
final String code;
|
final String code;
|
||||||
final bool isBatchControl;
|
|
||||||
const FlushMountedPresenceSensorChangeValueEvent({
|
const FlushMountedPresenceSensorChangeValueEvent({
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.code,
|
required this.code,
|
||||||
this.isBatchControl = false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -75,7 +75,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.nearDetection / 100).toDouble(),
|
value: (model.nearDetection / 100).clamp(0.0, double.infinity),
|
||||||
title: 'Nearest Detect Dist:',
|
title: 'Nearest Detect Dist:',
|
||||||
description: 'm',
|
description: 'm',
|
||||||
minValue: 0.0,
|
minValue: 0.0,
|
||||||
@ -92,7 +92,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.farDetection / 100).toDouble(),
|
value: (model.farDetection / 100).clamp(0.0, double.infinity),
|
||||||
title: 'Max Detect Dist:',
|
title: 'Max Detect Dist:',
|
||||||
description: 'm',
|
description: 'm',
|
||||||
minValue: 0.0,
|
minValue: 0.0,
|
||||||
@ -109,7 +109,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: model.presenceDelay.toDouble(),
|
value: model.sensiReduce.toDouble(),
|
||||||
title: 'Trigger Level:',
|
title: 'Trigger Level:',
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 3,
|
maxValue: 3,
|
||||||
@ -117,7 +117,7 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
|||||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||||
FlushMountedPresenceSensorBatchControlEvent(
|
FlushMountedPresenceSensorBatchControlEvent(
|
||||||
deviceIds: devicesIds,
|
deviceIds: devicesIds,
|
||||||
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||||
value: value,
|
value: value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -137,19 +137,21 @@ class FlushMountedPresenceSensorBatchControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.sensiReduce.toDouble()),
|
value: (model.presenceDelay / 10).toDouble(),
|
||||||
title: 'Target Confirm Time:',
|
title: 'Target Confirm Time:',
|
||||||
description: 's',
|
description: 's',
|
||||||
minValue: 0,
|
minValue: 0.0,
|
||||||
maxValue: 3,
|
maxValue: 0.5,
|
||||||
steps: 1,
|
steps: 0.1,
|
||||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
valuesPercision: 1,
|
||||||
FlushMountedPresenceSensorBatchControlEvent(
|
action: (double value) =>
|
||||||
deviceIds: devicesIds,
|
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
FlushMountedPresenceSensorBatchControlEvent(
|
||||||
value: value,
|
deviceIds: devicesIds,
|
||||||
),
|
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||||
),
|
value: (value * 10).toInt(),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: ((model.noneDelay / 10).toDouble()),
|
value: ((model.noneDelay / 10).toDouble()),
|
||||||
|
@ -15,7 +15,7 @@ import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_la
|
|||||||
|
|
||||||
class FlushMountedPresenceSensorControlView extends StatelessWidget
|
class FlushMountedPresenceSensorControlView extends StatelessWidget
|
||||||
with HelperResponsiveLayout {
|
with HelperResponsiveLayout {
|
||||||
const FlushMountedPresenceSensorControlView({super.key, required this.device});
|
const FlushMountedPresenceSensorControlView({required this.device, super.key});
|
||||||
|
|
||||||
final AllDevicesModel device;
|
final AllDevicesModel device;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.nearDetection / 100).toDouble(),
|
value: (model.nearDetection / 100).clamp(0.0, double.infinity),
|
||||||
title: 'Nearest Detect Dist:',
|
title: 'Nearest Detect Dist:',
|
||||||
description: 'm',
|
description: 'm',
|
||||||
minValue: 0.0,
|
minValue: 0.0,
|
||||||
@ -129,7 +129,7 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.farDetection / 100).toDouble(),
|
value: (model.farDetection / 100).clamp(0.0, double.infinity),
|
||||||
title: 'Max Detect Dist:',
|
title: 'Max Detect Dist:',
|
||||||
description: 'm',
|
description: 'm',
|
||||||
minValue: 0.0,
|
minValue: 0.0,
|
||||||
@ -145,20 +145,20 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.presenceDelay.toDouble()),
|
value: model.sensiReduce.toDouble(),
|
||||||
title: 'Trigger Level:',
|
title: 'Trigger Level:',
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 3,
|
maxValue: 3,
|
||||||
steps: 1,
|
steps: 1,
|
||||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
||||||
FlushMountedPresenceSensorChangeValueEvent(
|
FlushMountedPresenceSensorChangeValueEvent(
|
||||||
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
||||||
value: value,
|
value: value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.occurDistReduce.toDouble()),
|
value: model.occurDistReduce.toDouble(),
|
||||||
title: 'Indent Level:',
|
title: 'Indent Level:',
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 3,
|
maxValue: 3,
|
||||||
@ -171,21 +171,23 @@ class FlushMountedPresenceSensorControlView extends StatelessWidget
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: (model.sensiReduce.toDouble()),
|
value: (model.presenceDelay / 10).toDouble(),
|
||||||
|
valuesPercision: 1,
|
||||||
title: 'Target Confirm Time:',
|
title: 'Target Confirm Time:',
|
||||||
description: 's',
|
description: 's',
|
||||||
minValue: 0,
|
minValue: 0.0,
|
||||||
maxValue: 3,
|
maxValue: 0.5,
|
||||||
steps: 1,
|
steps: 0.1,
|
||||||
action: (int value) => context.read<FlushMountedPresenceSensorBloc>().add(
|
action: (double value) =>
|
||||||
FlushMountedPresenceSensorChangeValueEvent(
|
context.read<FlushMountedPresenceSensorBloc>().add(
|
||||||
code: FlushMountedPresenceSensorModel.codeSensiReduce,
|
FlushMountedPresenceSensorChangeValueEvent(
|
||||||
value: value,
|
code: FlushMountedPresenceSensorModel.codePresenceDelay,
|
||||||
),
|
value: (value * 10).toInt(),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
PresenceUpdateData(
|
PresenceUpdateData(
|
||||||
value: ((model.noneDelay / 10).toDouble()),
|
value: (model.noneDelay / 10).toDouble(),
|
||||||
description: 's',
|
description: 's',
|
||||||
title: 'Disappe Delay:',
|
title: 'Disappe Delay:',
|
||||||
minValue: 20,
|
minValue: 20,
|
||||||
|
@ -217,29 +217,31 @@ class SmartPowerBloc extends Bloc<SmartPowerEvent, SmartPowerState> {
|
|||||||
try {
|
try {
|
||||||
var status =
|
var status =
|
||||||
await DevicesManagementApi().getPowerClampInfo(event.deviceId);
|
await DevicesManagementApi().getPowerClampInfo(event.deviceId);
|
||||||
deviceStatus = PowerClampModel.fromJson(status);
|
deviceStatus = PowerClampModel.fromJson(status as Map<String, Object?>? ??{});
|
||||||
|
final phaseADataPoints = deviceStatus.status.phaseA.dataPoints;
|
||||||
|
final phaseBDataPoints = deviceStatus.status.phaseB.dataPoints;
|
||||||
|
final phaseCDataPoints = deviceStatus.status.phaseC.dataPoints;
|
||||||
phaseData = [
|
phaseData = [
|
||||||
{
|
{
|
||||||
'name': 'Phase A',
|
'name': 'Phase A',
|
||||||
'voltage': '${deviceStatus.status.phaseA.dataPoints[0].value / 10} V',
|
'voltage': '${(phaseADataPoints.elementAtOrNull(0)?.value as num? ?? 0) / 10} V',
|
||||||
'current': '${deviceStatus.status.phaseA.dataPoints[1].value / 10} A',
|
'current': '${(phaseADataPoints.elementAtOrNull(1)?.value as num? ?? 0) / 10} A',
|
||||||
'activePower': '${deviceStatus.status.phaseA.dataPoints[2].value} W',
|
'activePower': '${phaseADataPoints.elementAtOrNull(2)?.value??'N/A'} W',
|
||||||
'powerFactor': '${deviceStatus.status.phaseA.dataPoints[3].value}',
|
'powerFactor': '${phaseADataPoints.elementAtOrNull(3)?.value??'N/A'}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Phase B',
|
'name': 'Phase B',
|
||||||
'voltage': '${deviceStatus.status.phaseB.dataPoints[0].value / 10} V',
|
'voltage': '${(phaseBDataPoints .elementAtOrNull(0)?.value as num? ?? 0) / 10} V',
|
||||||
'current': '${deviceStatus.status.phaseB.dataPoints[1].value / 10} A',
|
'current': '${(phaseBDataPoints .elementAtOrNull(1)?.value as num? ?? 0) / 10} A',
|
||||||
'activePower': '${deviceStatus.status.phaseB.dataPoints[2].value} W',
|
'activePower': '${phaseBDataPoints.elementAtOrNull(2)?.value??'N/A'} W',
|
||||||
'powerFactor': '${deviceStatus.status.phaseB.dataPoints[3].value}',
|
'powerFactor': '${phaseBDataPoints.elementAtOrNull(3)?.value??'N/A'}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Phase C',
|
'name': 'Phase C',
|
||||||
'voltage': '${deviceStatus.status.phaseC.dataPoints[0].value / 10} V',
|
'voltage': '${(phaseCDataPoints.elementAtOrNull(0)?.value as num? ?? 0) / 10} V',
|
||||||
'current': '${deviceStatus.status.phaseC.dataPoints[1].value / 10} A',
|
'current': '${(phaseCDataPoints.elementAtOrNull(1)?.value as num? ?? 0) / 10} A',
|
||||||
'activePower': '${deviceStatus.status.phaseC.dataPoints[2].value} W',
|
'activePower': '${phaseCDataPoints.elementAtOrNull(2)?.value ?? 'N/A'} W',
|
||||||
'powerFactor': '${deviceStatus.status.phaseC.dataPoints[3].value}',
|
'powerFactor': '${phaseCDataPoints.elementAtOrNull(3)?.value ?? 'N/A'}',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
emit(GetDeviceStatus());
|
emit(GetDeviceStatus());
|
||||||
@ -785,7 +787,7 @@ class SmartPowerBloc extends Bloc<SmartPowerEvent, SmartPowerState> {
|
|||||||
void selectDateRange() async {
|
void selectDateRange() async {
|
||||||
DateTime startDate = dateTime!;
|
DateTime startDate = dateTime!;
|
||||||
DateTime endDate = DateTime(startDate.year, startDate.month + 1, 1)
|
DateTime endDate = DateTime(startDate.year, startDate.month + 1, 1)
|
||||||
.subtract(Duration(days: 1));
|
.subtract(const Duration(days: 1));
|
||||||
String formattedEndDate = DateFormat('dd/MM/yyyy').format(endDate);
|
String formattedEndDate = DateFormat('dd/MM/yyyy').format(endDate);
|
||||||
endChartDate = ' - $formattedEndDate';
|
endChartDate = ' - $formattedEndDate';
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ class PowerClampModel {
|
|||||||
|
|
||||||
factory PowerClampModel.fromJson(Map<String, dynamic> json) {
|
factory PowerClampModel.fromJson(Map<String, dynamic> json) {
|
||||||
return PowerClampModel(
|
return PowerClampModel(
|
||||||
productUuid: json['productUuid'],
|
productUuid: json['productUuid'] as String? ?? '',
|
||||||
productType: json['productType'],
|
productType: json['productType'] as String? ?? '',
|
||||||
status: PowerStatus.fromJson(json['status']),
|
status: PowerStatus.fromJson(json['status'] as Map<String, dynamic>? ?? {}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class PowerClampModel {
|
|||||||
return PowerClampModel(
|
return PowerClampModel(
|
||||||
productUuid: productUuid ?? this.productUuid,
|
productUuid: productUuid ?? this.productUuid,
|
||||||
productType: productType ?? this.productType,
|
productType: productType ?? this.productType,
|
||||||
status: statusPower ?? this.status,
|
status: statusPower ?? status,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,12 +46,10 @@ class PowerStatus {
|
|||||||
|
|
||||||
factory PowerStatus.fromJson(Map<String, dynamic> json) {
|
factory PowerStatus.fromJson(Map<String, dynamic> json) {
|
||||||
return PowerStatus(
|
return PowerStatus(
|
||||||
phaseA: Phase.fromJson(json['phaseA']),
|
phaseA: Phase.fromJson(json['phaseA']as List<dynamic>? ?? []),
|
||||||
phaseB: Phase.fromJson(json['phaseB']),
|
phaseB: Phase.fromJson(json['phaseB']as List<dynamic>? ?? []),
|
||||||
phaseC: Phase.fromJson(json['phaseC']),
|
phaseC: Phase.fromJson(json['phaseC']as List<dynamic>? ?? []),
|
||||||
general: Phase.fromJson(json['general']
|
general: Phase.fromJson(json['general']as List<dynamic>? ?? []
|
||||||
// List<DataPoint>.from(
|
|
||||||
// json['general'].map((x) => DataPoint.fromJson(x))),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,30 +67,30 @@ class Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DataPoint {
|
class DataPoint {
|
||||||
dynamic code;
|
final String? code;
|
||||||
dynamic customName;
|
final String? customName;
|
||||||
dynamic dpId;
|
final int? dpId;
|
||||||
dynamic time;
|
final int? time;
|
||||||
dynamic type;
|
final String? type;
|
||||||
dynamic value;
|
final dynamic value;
|
||||||
|
|
||||||
DataPoint({
|
DataPoint({
|
||||||
required this.code,
|
this.code,
|
||||||
required this.customName,
|
this.customName,
|
||||||
required this.dpId,
|
this.dpId,
|
||||||
required this.time,
|
this.time,
|
||||||
required this.type,
|
this.type,
|
||||||
required this.value,
|
this.value,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory DataPoint.fromJson(Map<String, dynamic> json) {
|
factory DataPoint.fromJson(Map<String, dynamic> json) {
|
||||||
return DataPoint(
|
return DataPoint(
|
||||||
code: json['code'],
|
code: json['code'] as String?,
|
||||||
customName: json['customName'],
|
customName: json['customName'] as String?,
|
||||||
dpId: json['dpId'],
|
dpId: json['dpId'] as int?,
|
||||||
time: json['time'],
|
time: json['time'] as int?,
|
||||||
type: json['type'],
|
type: json['type'] as String?,
|
||||||
value: json['value'],
|
value: json['value'] as dynamic,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class EnergyConsumptionPage extends StatefulWidget {
|
class EnergyConsumptionPage extends StatefulWidget {
|
||||||
@ -10,7 +10,8 @@ class EnergyConsumptionPage extends StatefulWidget {
|
|||||||
final Widget widget;
|
final Widget widget;
|
||||||
final Function()? onTap;
|
final Function()? onTap;
|
||||||
|
|
||||||
EnergyConsumptionPage({
|
const EnergyConsumptionPage({
|
||||||
|
super.key,
|
||||||
required this.chartData,
|
required this.chartData,
|
||||||
required this.totalConsumption,
|
required this.totalConsumption,
|
||||||
required this.date,
|
required this.date,
|
||||||
@ -91,11 +92,12 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: MediaQuery.of(context).size.height * 0.11,
|
height: MediaQuery.sizeOf(context).height * 0.09,
|
||||||
child: LineChart(
|
child: LineChart(
|
||||||
LineChartData(
|
LineChartData(
|
||||||
lineTouchData: LineTouchData(
|
lineTouchData: LineTouchData(
|
||||||
@ -151,7 +153,7 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
child: RotatedBox(
|
child: RotatedBox(
|
||||||
quarterTurns: -1,
|
quarterTurns: -1,
|
||||||
child: Text(_chartData[index].time,
|
child: Text(_chartData[index].time,
|
||||||
style: TextStyle(fontSize: 10)),
|
style: const TextStyle(fontSize: 10)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -190,8 +192,8 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
spots: _chartData
|
spots: _chartData
|
||||||
.asMap()
|
.asMap()
|
||||||
.entries
|
.entries
|
||||||
.map((entry) => FlSpot(entry.key.toDouble(),
|
.map((entry) => FlSpot(
|
||||||
entry.value.consumption))
|
entry.key.toDouble(), entry.value.consumption))
|
||||||
.toList(),
|
.toList(),
|
||||||
isCurved: true,
|
isCurved: true,
|
||||||
color: ColorsManager.primaryColor.withOpacity(0.6),
|
color: ColorsManager.primaryColor.withOpacity(0.6),
|
||||||
@ -218,7 +220,7 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
borderData: FlBorderData(
|
borderData: FlBorderData(
|
||||||
show: false,
|
show: false,
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Color(0xff023DFE).withOpacity(0.7),
|
color: const Color(0xff023DFE).withOpacity(0.7),
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -253,11 +255,9 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: widget.onTap,
|
onTap: widget.onTap,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SizedBox(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(5),
|
||||||
padding: const EdgeInsets.all(5),
|
child: Text(widget.date),
|
||||||
child: Text(widget.date),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -12,8 +12,7 @@ import 'package:syncrow_web/utils/constants/assets.dart';
|
|||||||
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
|
||||||
|
|
||||||
//Smart Power Clamp
|
//Smart Power Clamp
|
||||||
class SmartPowerDeviceControl extends StatelessWidget
|
class SmartPowerDeviceControl extends StatelessWidget with HelperResponsiveLayout {
|
||||||
with HelperResponsiveLayout {
|
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
|
|
||||||
const SmartPowerDeviceControl({super.key, required this.deviceId});
|
const SmartPowerDeviceControl({super.key, required this.deviceId});
|
||||||
@ -25,27 +24,27 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
..add(SmartPowerFetchDeviceEvent(deviceId)),
|
..add(SmartPowerFetchDeviceEvent(deviceId)),
|
||||||
child: BlocBuilder<SmartPowerBloc, SmartPowerState>(
|
child: BlocBuilder<SmartPowerBloc, SmartPowerState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final _blocProvider = BlocProvider.of<SmartPowerBloc>(context);
|
final blocProvider = BlocProvider.of<SmartPowerBloc>(context);
|
||||||
|
|
||||||
if (state is SmartPowerLoading) {
|
if (state is SmartPowerLoading) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
} else if (state is FakeState) {
|
} else if (state is FakeState) {
|
||||||
return _buildStatusControls(
|
return _buildStatusControls(
|
||||||
currentPage: _blocProvider.currentPage,
|
currentPage: blocProvider.currentPage,
|
||||||
context: context,
|
context: context,
|
||||||
blocProvider: _blocProvider,
|
blocProvider: blocProvider,
|
||||||
);
|
);
|
||||||
} else if (state is GetDeviceStatus) {
|
} else if (state is GetDeviceStatus) {
|
||||||
return _buildStatusControls(
|
return _buildStatusControls(
|
||||||
currentPage: _blocProvider.currentPage,
|
currentPage: blocProvider.currentPage,
|
||||||
context: context,
|
context: context,
|
||||||
blocProvider: _blocProvider,
|
blocProvider: blocProvider,
|
||||||
);
|
);
|
||||||
} else if (state is FilterRecordsState) {
|
} else if (state is FilterRecordsState) {
|
||||||
return _buildStatusControls(
|
return _buildStatusControls(
|
||||||
currentPage: _blocProvider.currentPage,
|
currentPage: blocProvider.currentPage,
|
||||||
context: context,
|
context: context,
|
||||||
blocProvider: _blocProvider,
|
blocProvider: blocProvider,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
@ -60,7 +59,7 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
required SmartPowerBloc blocProvider,
|
required SmartPowerBloc blocProvider,
|
||||||
required int currentPage,
|
required int currentPage,
|
||||||
}) {
|
}) {
|
||||||
PageController _pageController = PageController(initialPage: currentPage);
|
PageController pageController = PageController(initialPage: currentPage);
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||||
child: DeviceControlsContainer(
|
child: DeviceControlsContainer(
|
||||||
@ -85,25 +84,31 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
PowerClampInfoCard(
|
PowerClampInfoCard(
|
||||||
iconPath: Assets.powerActiveIcon,
|
iconPath: Assets.powerActiveIcon,
|
||||||
title: 'Active',
|
title: 'Active',
|
||||||
value: blocProvider
|
value: blocProvider.deviceStatus.status.general.dataPoints
|
||||||
.deviceStatus.status.general.dataPoints[2].value
|
.elementAtOrNull(2)
|
||||||
.toString(),
|
?.value
|
||||||
|
.toString() ??
|
||||||
|
'',
|
||||||
unit: '',
|
unit: '',
|
||||||
),
|
),
|
||||||
PowerClampInfoCard(
|
PowerClampInfoCard(
|
||||||
iconPath: Assets.voltMeterIcon,
|
iconPath: Assets.voltMeterIcon,
|
||||||
title: 'Current',
|
title: 'Current',
|
||||||
value: blocProvider
|
value: blocProvider.deviceStatus.status.general.dataPoints
|
||||||
.deviceStatus.status.general.dataPoints[1].value
|
.elementAtOrNull(1)
|
||||||
.toString(),
|
?.value
|
||||||
|
.toString() ??
|
||||||
|
'',
|
||||||
unit: ' A',
|
unit: ' A',
|
||||||
),
|
),
|
||||||
PowerClampInfoCard(
|
PowerClampInfoCard(
|
||||||
iconPath: Assets.frequencyIcon,
|
iconPath: Assets.frequencyIcon,
|
||||||
title: 'Frequency',
|
title: 'Frequency',
|
||||||
value: blocProvider
|
value: blocProvider.deviceStatus.status.general.dataPoints
|
||||||
.deviceStatus.status.general.dataPoints[4].value
|
.elementAtOrNull(4)
|
||||||
.toString(),
|
?.value
|
||||||
|
.toString() ??
|
||||||
|
'',
|
||||||
unit: ' Hz',
|
unit: ' Hz',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -142,7 +147,7 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
icon: const Icon(Icons.arrow_left),
|
icon: const Icon(Icons.arrow_left),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
blocProvider.add(SmartPowerArrowPressedEvent(-1));
|
blocProvider.add(SmartPowerArrowPressedEvent(-1));
|
||||||
_pageController.previousPage(
|
pageController.previousPage(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
@ -162,7 +167,7 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
icon: const Icon(Icons.arrow_right),
|
icon: const Icon(Icons.arrow_right),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
blocProvider.add(SmartPowerArrowPressedEvent(1));
|
blocProvider.add(SmartPowerArrowPressedEvent(1));
|
||||||
_pageController.nextPage(
|
pageController.nextPage(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
@ -177,7 +182,7 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: PageView(
|
child: PageView(
|
||||||
controller: _pageController,
|
controller: pageController,
|
||||||
onPageChanged: (int page) {
|
onPageChanged: (int page) {
|
||||||
blocProvider.add(SmartPowerPageChangedEvent(page));
|
blocProvider.add(SmartPowerPageChangedEvent(page));
|
||||||
},
|
},
|
||||||
@ -190,8 +195,8 @@ class SmartPowerDeviceControl extends StatelessWidget
|
|||||||
blocProvider.add(SelectDateEvent(context: context));
|
blocProvider.add(SelectDateEvent(context: context));
|
||||||
blocProvider.add(FilterRecordsByDateEvent(
|
blocProvider.add(FilterRecordsByDateEvent(
|
||||||
selectedDate: blocProvider.dateTime!,
|
selectedDate: blocProvider.dateTime!,
|
||||||
viewType: blocProvider
|
viewType:
|
||||||
.views[blocProvider.currentIndex]));
|
blocProvider.views[blocProvider.currentIndex]));
|
||||||
},
|
},
|
||||||
widget: blocProvider.dateSwitcher(),
|
widget: blocProvider.dateSwitcher(),
|
||||||
chartData: blocProvider.energyDataList.isNotEmpty
|
chartData: blocProvider.energyDataList.isNotEmpty
|
||||||
|
@ -46,14 +46,14 @@ final class DebouncedBatchControlDevicesService
|
|||||||
final BatchControlDevicesService decoratee;
|
final BatchControlDevicesService decoratee;
|
||||||
final Duration debounceDuration;
|
final Duration debounceDuration;
|
||||||
|
|
||||||
final _pendingRequests = <(List<String> uuids, String code, Object value)>[];
|
|
||||||
var _isProcessing = false;
|
|
||||||
|
|
||||||
DebouncedBatchControlDevicesService({
|
DebouncedBatchControlDevicesService({
|
||||||
required this.decoratee,
|
required this.decoratee,
|
||||||
this.debounceDuration = const Duration(milliseconds: 800),
|
this.debounceDuration = const Duration(milliseconds: 1500),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final _pendingRequests = <(List<String> uuids, String code, Object value)>[];
|
||||||
|
var _isProcessing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> batchControlDevices({
|
Future<bool> batchControlDevices({
|
||||||
required List<String> uuids,
|
required List<String> uuids,
|
||||||
@ -68,16 +68,26 @@ final class DebouncedBatchControlDevicesService
|
|||||||
|
|
||||||
await Future.delayed(debounceDuration);
|
await Future.delayed(debounceDuration);
|
||||||
|
|
||||||
final lastRequest = _pendingRequests.last;
|
final groupedRequests =
|
||||||
|
<String, (List<String> uuids, String code, Object value)>{};
|
||||||
|
for (final request in _pendingRequests) {
|
||||||
|
final (_, requestCode, requestValue) = request;
|
||||||
|
groupedRequests[requestCode] = request;
|
||||||
|
}
|
||||||
_pendingRequests.clear();
|
_pendingRequests.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final (lastRequestUuids, lastRequestCode, lastRequestValue) = lastRequest;
|
var allSuccessful = true;
|
||||||
return decoratee.batchControlDevices(
|
for (final request in groupedRequests.values) {
|
||||||
uuids: lastRequestUuids,
|
final (lastRequestUuids, lastRequestCode, lastRequestValue) = request;
|
||||||
code: lastRequestCode,
|
final success = await decoratee.batchControlDevices(
|
||||||
value: lastRequestValue,
|
uuids: lastRequestUuids,
|
||||||
);
|
code: lastRequestCode,
|
||||||
|
value: lastRequestValue,
|
||||||
|
);
|
||||||
|
if (!success) allSuccessful = false;
|
||||||
|
}
|
||||||
|
return allSuccessful;
|
||||||
} finally {
|
} finally {
|
||||||
_isProcessing = false;
|
_isProcessing = false;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ final class DebouncedControlDeviceService implements ControlDeviceService {
|
|||||||
|
|
||||||
DebouncedControlDeviceService({
|
DebouncedControlDeviceService({
|
||||||
required this.decoratee,
|
required this.decoratee,
|
||||||
this.debounceDuration = const Duration(milliseconds: 800),
|
this.debounceDuration = const Duration(milliseconds: 1500),
|
||||||
});
|
});
|
||||||
|
|
||||||
final _pendingRequests = <(String deviceUuid, Status status)>[];
|
final _pendingRequests = <(String deviceUuid, Status status)>[];
|
||||||
@ -59,15 +59,24 @@ final class DebouncedControlDeviceService implements ControlDeviceService {
|
|||||||
|
|
||||||
await Future.delayed(debounceDuration);
|
await Future.delayed(debounceDuration);
|
||||||
|
|
||||||
final lastRequest = _pendingRequests.last;
|
final groupedRequests = <String, (String deviceUuid, Status status)>{};
|
||||||
|
for (final request in _pendingRequests) {
|
||||||
|
final (_, requestStatus) = request;
|
||||||
|
groupedRequests[requestStatus.code] = request;
|
||||||
|
}
|
||||||
_pendingRequests.clear();
|
_pendingRequests.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final (lastRequestDeviceUuid, lastRequestStatus) = lastRequest;
|
var allSuccessful = true;
|
||||||
return decoratee.controlDevice(
|
for (final request in groupedRequests.values) {
|
||||||
deviceUuid: lastRequestDeviceUuid,
|
final (lastRequestDeviceUuid, lastRequestStatus) = request;
|
||||||
status: lastRequestStatus,
|
final success = await decoratee.controlDevice(
|
||||||
);
|
deviceUuid: lastRequestDeviceUuid,
|
||||||
|
status: lastRequestStatus,
|
||||||
|
);
|
||||||
|
if (!success) allSuccessful = false;
|
||||||
|
}
|
||||||
|
return allSuccessful;
|
||||||
} finally {
|
} finally {
|
||||||
_isProcessing = false;
|
_isProcessing = false;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user