mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-16 18:16:21 +00:00
power clamp
This commit is contained in:
216
lib/features/devices/bloc/power_clamp_bloc/power_clamp_bloc.dart
Normal file
216
lib/features/devices/bloc/power_clamp_bloc/power_clamp_bloc.dart
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_state.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/power_clamp_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
|
||||||
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
|
|
||||||
|
class PowerClampBloc extends Bloc<PowerClampEvent, PowerClampState> {
|
||||||
|
final String PCId;
|
||||||
|
PowerClampBloc({
|
||||||
|
required this.PCId,
|
||||||
|
}) : super(const PowerClampState()) {
|
||||||
|
on<PowerClampInitial>(_fetchStatus);
|
||||||
|
on<ReportLogsInitial>(fetchLogsForLastMonth);
|
||||||
|
on<FetchEnergyData>(_mapReportToEnergyData);
|
||||||
|
on<SelectDateEvent>(selectTimeOfLinePassword);
|
||||||
|
}
|
||||||
|
//SelectDateEvent
|
||||||
|
Timer? _timer;
|
||||||
|
DateTime? dateTime = DateTime.now();
|
||||||
|
|
||||||
|
String formattedDate = DateFormat('yyyy/MM/dd').format(DateTime.now());
|
||||||
|
bool lowBattery = false;
|
||||||
|
bool closingReminder = false;
|
||||||
|
bool doorAlarm = false;
|
||||||
|
PowerClampModel deviceStatus =
|
||||||
|
PowerClampModel(doorContactState: false, batteryPercentage: 0);
|
||||||
|
|
||||||
|
void _fetchStatus(
|
||||||
|
PowerClampInitial event, Emitter<PowerClampState> emit) async {
|
||||||
|
emit(PowerClampLoadingState());
|
||||||
|
try {
|
||||||
|
var response = await DevicesAPI.getDeviceStatus(PCId);
|
||||||
|
List<StatusModel> statusModelList = [];
|
||||||
|
for (var status in response['status']) {
|
||||||
|
statusModelList.add(StatusModel.fromJson(status));
|
||||||
|
}
|
||||||
|
deviceStatus = PowerClampModel.fromJson(
|
||||||
|
statusModelList,
|
||||||
|
);
|
||||||
|
emit(UpdateState(powerClampModel: deviceStatus));
|
||||||
|
Future.delayed(const Duration(milliseconds: 500));
|
||||||
|
// _listenToChanges();
|
||||||
|
} catch (e) {
|
||||||
|
emit(PowerClampFailedState(errorMessage: e.toString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceReport recordGroups =
|
||||||
|
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||||
|
|
||||||
|
Future<void> fetchLogsForLastMonth(
|
||||||
|
ReportLogsInitial event, Emitter<PowerClampState> emit) async {
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
|
||||||
|
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||||
|
|
||||||
|
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||||
|
int endTime = now.millisecondsSinceEpoch;
|
||||||
|
try {
|
||||||
|
emit(PowerClampLoadingState());
|
||||||
|
var response = await DevicesAPI.getReportLogs(
|
||||||
|
startTime: startTime.toString(),
|
||||||
|
endTime: endTime.toString(),
|
||||||
|
deviceUuid: PCId,
|
||||||
|
code: event.code!,
|
||||||
|
);
|
||||||
|
recordGroups = response;
|
||||||
|
emit(UpdateState(powerClampModel: deviceStatus));
|
||||||
|
add(FetchEnergyData()); // Trigger mapping to EnergyData
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_listenToChanges() {
|
||||||
|
try {
|
||||||
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$PCId');
|
||||||
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
|
stream.listen((DatabaseEvent event) async {
|
||||||
|
if (_timer != null) {
|
||||||
|
await Future.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
|
usersMap['status'].forEach((element) {
|
||||||
|
statusList.add(StatusModel(code: element['code'], value: true));
|
||||||
|
});
|
||||||
|
|
||||||
|
deviceStatus = PowerClampModel.fromJson(statusList);
|
||||||
|
if (!isClosed) {
|
||||||
|
add(
|
||||||
|
PowerClampSwitch(switchD: deviceStatus.doorContactState),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Function: Convert the device report data into EnergyData and emit it.
|
||||||
|
void _mapReportToEnergyData(
|
||||||
|
FetchEnergyData event, Emitter<PowerClampState> emit) {
|
||||||
|
try {
|
||||||
|
List<EnergyData> energyDataList = recordGroups.data
|
||||||
|
?.map((event) {
|
||||||
|
if (event.code == "VoltageA" && event.eventTime != null) {
|
||||||
|
// Convert eventTime to readable format
|
||||||
|
DateTime eventDateTime =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(event.eventTime!);
|
||||||
|
String formattedTime =
|
||||||
|
"${eventDateTime.hour}:${eventDateTime.minute.toString().padLeft(2, '0')} ${eventDateTime.hour >= 12 ? 'PM' : 'AM'}";
|
||||||
|
double value = double.tryParse(event.value ?? "0") ?? 0;
|
||||||
|
return EnergyData(
|
||||||
|
formattedTime, value / 1000); // Assume kWh format
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.where((data) => data != null)
|
||||||
|
.cast<EnergyData>()
|
||||||
|
.toList() ??
|
||||||
|
[];
|
||||||
|
|
||||||
|
emit(EnergyDataState(energyData: energyDataList));
|
||||||
|
} catch (e) {
|
||||||
|
emit(PowerClampFailedState(errorMessage: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectTimeOfLinePassword(
|
||||||
|
SelectDateEvent event, Emitter<PowerClampState> emit) async {
|
||||||
|
emit(ChangeTimeState());
|
||||||
|
final DateTime? picked = await showDatePicker(
|
||||||
|
context: event.context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime(1905),
|
||||||
|
lastDate: DateTime(2101),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final selectedDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
final selectedTimestamp = DateTime(
|
||||||
|
selectedDateTime.year,
|
||||||
|
selectedDateTime.month,
|
||||||
|
selectedDateTime.day,
|
||||||
|
selectedDateTime.hour,
|
||||||
|
selectedDateTime.minute,
|
||||||
|
).millisecondsSinceEpoch ~/
|
||||||
|
1000; // Divide by 1000 to remove milliseconds
|
||||||
|
|
||||||
|
|
||||||
|
DateTime dateTime =
|
||||||
|
selectedDateTime; // Assuming this is your DateTime object
|
||||||
|
formattedDate = DateFormat('yyyy/MM/dd').format(dateTime);
|
||||||
|
emit(DateSelectedState());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentIndex = 0;
|
||||||
|
final List<String> views = ['Day', 'Month', 'Year'];
|
||||||
|
|
||||||
|
Widget dateSwitcher() {
|
||||||
|
void switchView(int direction) {
|
||||||
|
currentIndex = (currentIndex + direction + views.length) % views.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (BuildContext context, StateSetter setState) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.arrow_left),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
switchView(-1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
views[currentIndex],
|
||||||
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.arrow_right),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
switchView(1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
abstract class PowerClampEvent extends Equatable {
|
||||||
|
const PowerClampEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerClampLoading extends PowerClampEvent {}
|
||||||
|
|
||||||
|
class PowerClampSwitch extends PowerClampEvent {
|
||||||
|
final bool switchD;
|
||||||
|
final String deviceId;
|
||||||
|
final String productId;
|
||||||
|
const PowerClampSwitch(
|
||||||
|
{required this.switchD, this.deviceId = '', this.productId = ''});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [switchD, deviceId, productId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerClampUpdated extends PowerClampEvent {}
|
||||||
|
|
||||||
|
class FetchEnergyData extends PowerClampEvent {}
|
||||||
|
|
||||||
|
class SelectDateEvent extends PowerClampEvent {
|
||||||
|
BuildContext context;
|
||||||
|
SelectDateEvent({required this.context});
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerClampInitial extends PowerClampEvent {
|
||||||
|
const PowerClampInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReportLogsInitial extends PowerClampEvent {
|
||||||
|
final String? code;
|
||||||
|
const ReportLogsInitial({required this.code});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [code!];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerClampChangeStatus extends PowerClampEvent {}
|
||||||
|
|
||||||
|
class GetCounterEvent extends PowerClampEvent {
|
||||||
|
final String deviceCode;
|
||||||
|
const GetCounterEvent({required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleLowBatteryEvent extends PowerClampEvent {
|
||||||
|
final bool isLowBatteryEnabled;
|
||||||
|
|
||||||
|
const ToggleLowBatteryEvent(this.isLowBatteryEnabled);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [isLowBatteryEnabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleClosingReminderEvent extends PowerClampEvent {
|
||||||
|
final bool isClosingReminderEnabled;
|
||||||
|
|
||||||
|
const ToggleClosingReminderEvent(this.isClosingReminderEnabled);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [isClosingReminderEnabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToggleDoorAlarmEvent extends PowerClampEvent {
|
||||||
|
final bool isDoorAlarmEnabled;
|
||||||
|
|
||||||
|
const ToggleDoorAlarmEvent(this.isDoorAlarmEnabled);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [isDoorAlarmEnabled];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SetCounterValue extends PowerClampEvent {
|
||||||
|
final Duration duration;
|
||||||
|
final String deviceCode;
|
||||||
|
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration, deviceCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StartTimer extends PowerClampEvent {
|
||||||
|
final int duration;
|
||||||
|
|
||||||
|
const StartTimer(this.duration);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
class TickTimer extends PowerClampEvent {
|
||||||
|
final int remainingTime;
|
||||||
|
|
||||||
|
const TickTimer(this.remainingTime);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [remainingTime];
|
||||||
|
}
|
||||||
|
|
||||||
|
class StopTimer extends PowerClampEvent {}
|
||||||
|
|
||||||
|
class OnClose extends PowerClampEvent {}
|
@ -0,0 +1,48 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/power_clamp_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
|
||||||
|
|
||||||
|
class PowerClampState extends Equatable {
|
||||||
|
const PowerClampState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PowerClampInitialState extends PowerClampState {}
|
||||||
|
|
||||||
|
class PowerClampLoadingState extends PowerClampState {}
|
||||||
|
class ChangeTimeState extends PowerClampState {}
|
||||||
|
class DateSelectedState extends PowerClampState {}
|
||||||
|
//DateSelectedState
|
||||||
|
|
||||||
|
class PowerClampFailedState extends PowerClampState {
|
||||||
|
final String errorMessage;
|
||||||
|
|
||||||
|
const PowerClampFailedState({required this.errorMessage});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [errorMessage];
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateState extends PowerClampState {
|
||||||
|
final PowerClampModel powerClampModel;
|
||||||
|
const UpdateState({required this.powerClampModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [powerClampModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingNewSate extends PowerClampState {
|
||||||
|
final PowerClampModel powerClampModel;
|
||||||
|
const LoadingNewSate({required this.powerClampModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [powerClampModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
class EnergyDataState extends PowerClampState {
|
||||||
|
final List<EnergyData> energyData;
|
||||||
|
|
||||||
|
const EnergyDataState({required this.energyData});
|
||||||
|
}
|
28
lib/features/devices/model/power_clamp_model.dart
Normal file
28
lib/features/devices/model/power_clamp_model.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
|
|
||||||
|
class PowerClampModel {
|
||||||
|
dynamic doorContactState;
|
||||||
|
dynamic batteryPercentage;
|
||||||
|
|
||||||
|
PowerClampModel({
|
||||||
|
required this.doorContactState,
|
||||||
|
required this.batteryPercentage,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PowerClampModel.fromJson(List<StatusModel> jsonList) {
|
||||||
|
late dynamic _doorContactState;
|
||||||
|
late dynamic _batteryPercentage;
|
||||||
|
|
||||||
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
|
if (jsonList[i].code == 'VoltageA') {
|
||||||
|
_doorContactState = jsonList[i].value ?? false;
|
||||||
|
} else if (jsonList[i].code == 'CurrentA') {
|
||||||
|
_batteryPercentage = jsonList[i].value ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PowerClampModel(
|
||||||
|
doorContactState: _doorContactState,
|
||||||
|
batteryPercentage: _batteryPercentage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -120,6 +120,7 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
),
|
),
|
||||||
lineBarsData: [
|
lineBarsData: [
|
||||||
LineChartBarData(
|
LineChartBarData(
|
||||||
|
preventCurveOvershootingThreshold: 0.1,
|
||||||
curveSmoothness: 0.5,
|
curveSmoothness: 0.5,
|
||||||
preventCurveOverShooting: true,
|
preventCurveOverShooting: true,
|
||||||
aboveBarData: BarAreaData(),
|
aboveBarData: BarAreaData(),
|
||||||
@ -148,7 +149,7 @@ class _EnergyConsumptionPageState extends State<EnergyConsumptionPage> {
|
|||||||
show: false,
|
show: false,
|
||||||
),
|
),
|
||||||
isStrokeCapRound: true,
|
isStrokeCapRound: true,
|
||||||
barWidth: 6,
|
barWidth: 2,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
borderData: FlBorderData(
|
borderData: FlBorderData(
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_event.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/power_clamp_bloc/power_clamp_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
import 'package:syncrow_app/features/devices/model/power_clamp_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_chart.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_info_card.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/power_clamp/power_info_card.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
@ -34,19 +34,26 @@ class _PowerClampPageState extends State<PowerClampPage> {
|
|||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: 'Power Clamp',
|
title: 'Power Clamp',
|
||||||
child: BlocProvider(
|
child: BlocProvider(
|
||||||
create: (context) => DoorSensorBloc(DSId: widget.device?.uuid ?? '')
|
create: (context) => PowerClampBloc(PCId: widget.device?.uuid ?? '')
|
||||||
..add(const DoorSensorInitial()),
|
..add(const PowerClampInitial())
|
||||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
..add(ReportLogsInitial(code: 'VoltageA')),
|
||||||
|
child: BlocBuilder<PowerClampBloc, PowerClampState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
final _blocProvider = BlocProvider.of<PowerClampBloc>(context);
|
||||||
DoorSensorModel model =
|
PowerClampModel model =
|
||||||
DoorSensorModel(batteryPercentage: 0, doorContactState: false);
|
PowerClampModel(batteryPercentage: 0, doorContactState: false);
|
||||||
|
List<EnergyData> chartData = [];
|
||||||
|
|
||||||
if (state is LoadingNewSate) {
|
if (state is LoadingNewSate) {
|
||||||
model = state.doorSensor;
|
model = state.powerClampModel;
|
||||||
} else if (state is UpdateState) {
|
} else if (state is UpdateState) {
|
||||||
model = state.doorSensor;
|
model = state.powerClampModel;
|
||||||
|
} else if (state is EnergyDataState) {
|
||||||
|
chartData = state.energyData;
|
||||||
|
print(chartData);
|
||||||
}
|
}
|
||||||
return state is DoorSensorLoadingState
|
|
||||||
|
return state is PowerClampLoadingState
|
||||||
? const Center(
|
? const Center(
|
||||||
child: DefaultContainer(
|
child: DefaultContainer(
|
||||||
width: 50,
|
width: 50,
|
||||||
@ -58,7 +65,7 @@ class _PowerClampPageState extends State<PowerClampPage> {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: RefreshIndicator(
|
child: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
doorSensorBloc.add(const DoorSensorInitial());
|
_blocProvider.add(const PowerClampInitial());
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: 25),
|
padding: EdgeInsets.only(top: 25),
|
||||||
@ -68,6 +75,8 @@ class _PowerClampPageState extends State<PowerClampPage> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
_currentPage = page;
|
_currentPage = page;
|
||||||
});
|
});
|
||||||
|
_blocProvider.add(
|
||||||
|
const ReportLogsInitial(code: 'VoltageA'));
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return DefaultContainer(
|
return DefaultContainer(
|
||||||
@ -78,125 +87,178 @@ class _PowerClampPageState extends State<PowerClampPage> {
|
|||||||
top: 25,
|
top: 25,
|
||||||
bottom: 20),
|
bottom: 20),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('Energy usage'),
|
Text('Energy usage'),
|
||||||
const Row(
|
const Row(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.end,
|
CrossAxisAlignment.end,
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.spaceBetween,
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
BodyLarge(
|
BodyLarge(
|
||||||
text:
|
text:
|
||||||
'Total Energy \nConsumption',
|
'Total Energy \nConsumption',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
BodyLarge(
|
BodyLarge(
|
||||||
text: '8623.20 ',
|
text: '8623.20 ',
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
),
|
),
|
||||||
BodySmall(text: 'kWh')
|
BodySmall(text: 'kWh')
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
Row(
|
const Row(
|
||||||
mainAxisAlignment:
|
mainAxisAlignment:
|
||||||
MainAxisAlignment.spaceBetween,
|
MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
PowerClampInfoCard(
|
PowerClampInfoCard(
|
||||||
iconPath: Assets.powerActiveIcon,
|
iconPath:
|
||||||
title: 'Active',
|
Assets.powerActiveIcon,
|
||||||
value: '700',
|
title: 'Active',
|
||||||
unit: ' w',
|
value: '700',
|
||||||
),
|
unit: ' w',
|
||||||
PowerClampInfoCard(
|
),
|
||||||
iconPath: Assets.voltMeterIcon,
|
PowerClampInfoCard(
|
||||||
title: 'Current',
|
iconPath: Assets.voltMeterIcon,
|
||||||
value: '3.06',
|
title: 'Current',
|
||||||
unit: ' A',
|
value: '3.06',
|
||||||
),
|
unit: ' A',
|
||||||
PowerClampInfoCard(
|
),
|
||||||
iconPath: Assets.frequencyIcon,
|
PowerClampInfoCard(
|
||||||
title: 'Frequency',
|
iconPath: Assets.frequencyIcon,
|
||||||
value: '50',
|
title: 'Frequency',
|
||||||
unit: ' Hz',
|
value: '50',
|
||||||
),
|
unit: ' Hz',
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
SizedBox(
|
),
|
||||||
height: 20,
|
SizedBox(
|
||||||
),
|
height: 20,
|
||||||
Row(
|
),
|
||||||
mainAxisAlignment:
|
Row(
|
||||||
MainAxisAlignment.spaceBetween,
|
mainAxisAlignment:
|
||||||
children: [
|
MainAxisAlignment.spaceBetween,
|
||||||
Column(
|
children: [
|
||||||
crossAxisAlignment:
|
Column(
|
||||||
CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
children: [
|
CrossAxisAlignment.start,
|
||||||
BodyMedium(
|
children: [
|
||||||
text: 'Total consumption',
|
BodyMedium(
|
||||||
fontSize: 12,
|
text: 'Total consumption',
|
||||||
fontWeight: FontWeight.w700,
|
fontSize: 12,
|
||||||
),
|
fontWeight: FontWeight.w700,
|
||||||
Text(
|
),
|
||||||
'10/08/2024',
|
Text(
|
||||||
style: TextStyle(
|
'10/08/2024',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 8,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w400),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
text: '1000.00 ',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight:
|
||||||
|
FontWeight.w700),
|
||||||
|
BodyMedium(
|
||||||
|
text: 'kWh',
|
||||||
fontSize: 8,
|
fontSize: 8,
|
||||||
fontWeight:
|
fontWeight:
|
||||||
FontWeight.w400),
|
FontWeight.w700),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
BodyMedium(
|
|
||||||
text: '1000.00 ',
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.w700),
|
|
||||||
BodyMedium(
|
|
||||||
text: 'kWh',
|
|
||||||
fontSize: 8,
|
|
||||||
fontWeight:
|
|
||||||
FontWeight.w700),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 310,
|
|
||||||
child: EnergyConsumptionPage(
|
|
||||||
chartData: [
|
|
||||||
EnergyData('12:00 AM', 4.0),
|
|
||||||
EnergyData('01:00 AM', 3.5),
|
|
||||||
EnergyData('02:00 AM', 3.8),
|
|
||||||
EnergyData('03:00 AM', 3.2),
|
|
||||||
EnergyData('04:00 AM', 4.0),
|
|
||||||
EnergyData('05:00 AM', 3.4),
|
|
||||||
EnergyData('06:00 AM', 3.2),
|
|
||||||
EnergyData('07:00 AM', 3.5),
|
|
||||||
EnergyData('08:00 AM', 3.8),
|
|
||||||
EnergyData('09:00 AM', 3.6),
|
|
||||||
EnergyData('10:00 AM', 3.9),
|
|
||||||
EnergyData('11:00 AM', 4.0),
|
|
||||||
],
|
],
|
||||||
totalConsumption: 100.0,
|
|
||||||
date: '10/08/2024',
|
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
],
|
height: 290,
|
||||||
),
|
child: EnergyConsumptionPage(
|
||||||
|
chartData: chartData.isNotEmpty
|
||||||
|
? chartData
|
||||||
|
: [
|
||||||
|
EnergyData(
|
||||||
|
'12:00 AM', 4.0),
|
||||||
|
EnergyData(
|
||||||
|
'01:00 AM', 3.5),
|
||||||
|
EnergyData(
|
||||||
|
'02:00 AM', 3.8),
|
||||||
|
EnergyData(
|
||||||
|
'03:00 AM', 3.2),
|
||||||
|
EnergyData(
|
||||||
|
'04:00 AM', 4.0),
|
||||||
|
EnergyData(
|
||||||
|
'05:00 AM', 3.4),
|
||||||
|
EnergyData(
|
||||||
|
'06:00 AM', 3.2),
|
||||||
|
EnergyData(
|
||||||
|
'07:00 AM', 3.5),
|
||||||
|
EnergyData(
|
||||||
|
'08:00 AM', 3.8),
|
||||||
|
EnergyData(
|
||||||
|
'09:00 AM', 3.6),
|
||||||
|
EnergyData(
|
||||||
|
'10:00 AM', 3.9),
|
||||||
|
EnergyData(
|
||||||
|
'11:00 AM', 4.0),
|
||||||
|
],
|
||||||
|
totalConsumption: chartData.fold(
|
||||||
|
0,
|
||||||
|
(sum, data) =>
|
||||||
|
sum + data.consumption),
|
||||||
|
date: '10/08/2024',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
DefaultContainer(
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
color: ColorsManager.grayBox,
|
||||||
|
child: SizedBox(
|
||||||
|
child: _blocProvider
|
||||||
|
.dateSwitcher(),
|
||||||
|
)),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
_blocProvider.add(
|
||||||
|
SelectDateEvent(
|
||||||
|
context: context));
|
||||||
|
},
|
||||||
|
child: DefaultContainer(
|
||||||
|
color:
|
||||||
|
ColorsManager.grayBox,
|
||||||
|
child: SizedBox(
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets
|
||||||
|
.all(5),
|
||||||
|
child: Text(
|
||||||
|
_blocProvider
|
||||||
|
.formattedDate),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -164,15 +164,14 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
|||||||
PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
pageBuilder: (context, animation1, animation2) =>
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
WaterHeaterPage(device: device)));
|
WaterHeaterPage(device: device)));
|
||||||
// case DeviceType.DS:
|
case DeviceType.DS:
|
||||||
// Navigator.push(
|
Navigator.push(
|
||||||
// context,
|
context,
|
||||||
// PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
// pageBuilder: (context, animation1, animation2) =>
|
pageBuilder: (context, animation1, animation2) =>
|
||||||
// DoorSensorScreen(device: device)));
|
DoorSensorScreen(device: device)));
|
||||||
|
|
||||||
|
case DeviceType.PC:
|
||||||
case DeviceType.DS:
|
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
PageRouteBuilder(
|
PageRouteBuilder(
|
||||||
|
@ -55,7 +55,7 @@ enum DeviceType {
|
|||||||
ThreeTouch,
|
ThreeTouch,
|
||||||
GarageDoor,
|
GarageDoor,
|
||||||
WaterLeak,
|
WaterLeak,
|
||||||
|
PC,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +87,7 @@ Map<String, DeviceType> devicesTypesMap = {
|
|||||||
"3GT": DeviceType.ThreeTouch,
|
"3GT": DeviceType.ThreeTouch,
|
||||||
"GD": DeviceType.GarageDoor,
|
"GD": DeviceType.GarageDoor,
|
||||||
"WL": DeviceType.WaterLeak,
|
"WL": DeviceType.WaterLeak,
|
||||||
|
"PC": DeviceType.PC,
|
||||||
};
|
};
|
||||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||||
DeviceType.AC: [
|
DeviceType.AC: [
|
||||||
@ -471,6 +472,43 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
|||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
DeviceType.WaterLeak: [],
|
DeviceType.WaterLeak: [],
|
||||||
|
DeviceType.PC: [
|
||||||
|
FunctionModel(
|
||||||
|
code: 'switch_1',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_1',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'tr_timecon',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 120, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'countdown_alarm',
|
||||||
|
type: functionTypesMap['Integer'],
|
||||||
|
values: ValueModel.fromJson(
|
||||||
|
{"unit": "s", "min": 0, "max": 86400, "scale": 0, "step": 1})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'door_control_1',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ['open', 'open']
|
||||||
|
})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'voice_control_1',
|
||||||
|
type: functionTypesMap['Boolean'],
|
||||||
|
values: ValueModel.fromJson({})),
|
||||||
|
FunctionModel(
|
||||||
|
code: 'door_state_1',
|
||||||
|
type: functionTypesMap['Enum'],
|
||||||
|
values: ValueModel.fromJson({
|
||||||
|
"range": ["unclosed_time", "close_time_alarm", "none"]
|
||||||
|
})),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TempModes { hot, cold, wind }
|
enum TempModes { hot, cold, wind }
|
||||||
|
Reference in New Issue
Block a user