working on water heater

This commit is contained in:
ashrafzarkanisala
2024-09-17 00:22:51 +03:00
parent b18b96064a
commit 60b51657a6
10 changed files with 493 additions and 1 deletions

View File

@ -1,7 +1,10 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/fake_door_sensor.dart';
import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/devices_mang_api.dart';
import '../models/fake_heater_device.dart';
part 'device_managment_event.dart'; part 'device_managment_event.dart';
part 'device_managment_state.dart'; part 'device_managment_state.dart';
@ -31,6 +34,11 @@ class DeviceManagementBloc
try { try {
final devices = await DevicesManagementApi().fetchDevices(); final devices = await DevicesManagementApi().fetchDevices();
_selectedDevices.clear(); _selectedDevices.clear();
/// add fake device for heater
devices.insert(0, fakeWaterHeaterDevice);
devices.insert(1, fakeMainDoorSensor);
////
_devices = devices; _devices = devices;
_filteredDevices = devices; _filteredDevices = devices;
_calculateDeviceCounts(); _calculateDeviceCounts();

View File

@ -19,6 +19,7 @@ import 'package:syncrow_web/pages/device_managment/two_gang_switch/view/wall_lig
import 'package:syncrow_web/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart';
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_batch_control.dart'; import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_batch_control.dart';
import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_conrtols.dart'; import 'package:syncrow_web/pages/device_managment/wall_sensor/view/wall_sensor_conrtols.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/view/water_heater_device_control.dart';
mixin RouteControlsBasedCode { mixin RouteControlsBasedCode {
Widget routeControlsWidgets({required AllDevicesModel device}) { Widget routeControlsWidgets({required AllDevicesModel device}) {
@ -53,6 +54,8 @@ mixin RouteControlsBasedCode {
); );
case 'AC': case 'AC':
return AcDeviceControlsView(device: device); return AcDeviceControlsView(device: device);
case 'WH':
return WaterHeaterDeviceControl(device: device,);
default: default:
return const SizedBox(); return const SizedBox();
} }

View File

@ -0,0 +1,33 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
AllDevicesModel fakeMainDoorSensor = AllDevicesModel(
room: DevicesModelRoom(
uuid: "12de8f60-7104-4726-b5f8-ea426c0c7c3d", name: "Main Hall"),
unit: DevicesModelUnit(
uuid: "08fd3dcf-d13a-40db-970d-d0ce893df30e", name: "Entrance Unit 1"),
productUuid: "fake-uuid-main-door-sensor",
productType: "DS",
permissionType: "CONTROLLABLE",
activeTime: 1722178888,
category: "sensor",
categoryName: "Door Sensor",
createTime: 1722178888,
gatewayId: "b49df7395gfd8c19047krmk",
icon: "smart/icon/bay1642572935122vdsS/2b2f5fffaa5bbf81c3164fc313df2023.png",
ip: "",
lat: "31.92",
localKey: "A/43+<n/![jk>:7M",
lon: "35.85",
model: "D03ZLSDSA2",
name: "Main Door Sensor",
nodeId: "70a523ffece8a7f9",
online: true,
ownerId: "199300932",
sub: true,
timeZone: "+03:00",
updateTime: 1723627123,
uuid: "9c32dac5-ce0c-4c85-b45c-8e16511174cg",
batteryLevel: 85,
);

View File

@ -0,0 +1,33 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
AllDevicesModel fakeWaterHeaterDevice = AllDevicesModel(
room: DevicesModelRoom(
uuid: "75ea7d60-5104-4726-b5f8-ea426c0c6a1b", name: "Kitchen"),
unit: DevicesModelUnit(
uuid: "04fd1dcf-f24a-40db-970d-d0be884ed30f", name: "Flat 101"),
productUuid: "fake-uuid-kitchen-water-heater",
productType: "WH",
permissionType: "CONTROLLABLE",
activeTime: 1722173778,
category: "kg",
categoryName: "Water Heater",
createTime: 1722173778,
gatewayId: "bf0294123ed2c19067skrk",
icon: "smart/icon/bay1642572935385vcsA/2b1f5efbaa5bbf81c3164fa312cf2032.png",
ip: "",
lat: "31.97",
localKey: "T/39+<l/![iv>:9M",
lon: "35.89",
model: "S01ZLSWBSA3",
name: "Kitchen Water Heater",
nodeId: "60a423fffed5a7f6",
online: true,
ownerId: "199200732",
sub: true,
timeZone: "+03:00",
updateTime: 1723626515,
uuid: "5b31dae4-ce9c-4c70-b52b-7e150654sdf56",
batteryLevel: null,
);

View File

@ -10,6 +10,7 @@ class ToggleWidget extends StatelessWidget {
final String code; final String code;
final String deviceId; final String deviceId;
final String label; final String label;
final String? icon;
final Function(dynamic value) onChange; final Function(dynamic value) onChange;
const ToggleWidget({ const ToggleWidget({
@ -19,6 +20,7 @@ class ToggleWidget extends StatelessWidget {
required this.deviceId, required this.deviceId,
required this.label, required this.label,
required this.onChange, required this.onChange,
this.icon,
}); });
@override @override
@ -42,7 +44,7 @@ class ToggleWidget extends StatelessWidget {
child: Container( child: Container(
color: ColorsManager.whiteColors, color: ColorsManager.whiteColors,
child: SvgPicture.asset( child: SvgPicture.asset(
Assets.lightPulp, icon ?? Assets.lightPulp,
width: 60, width: 60,
height: 60, height: 60,
fit: BoxFit.cover, fit: BoxFit.cover,

View File

@ -0,0 +1,132 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
part 'water_heater_event.dart';
part 'water_heater_state.dart';
class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
WaterHeaterBloc() : super(WaterHeaterInitial()) {
on<WaterHeaterFetchStatusEvent>(_fetchWaterHeaterStatus);
on<ToggleWaterHeaterEvent>(_controlWaterHeater);
on<UpdateScheduleEvent>(_updateScheduleEvent);
on<StopScheduleEvent>(_stopScheduleEvent);
}
late WaterHeaterStatusModel deviceStatus;
Timer? _timer;
FutureOr<void> _updateScheduleEvent(
UpdateScheduleEvent event,
Emitter<WaterHeaterState> emit,
) {
emit(WaterHeaterScheduleState(
scheduleType: event.scheduleType,
hours: event.hours,
minutes: event.minutes,
isActive: true,
));
}
FutureOr<void> _stopScheduleEvent(
StopScheduleEvent event,
Emitter<WaterHeaterState> emit,
) {
if (state is WaterHeaterScheduleState) {
final currentState = state as WaterHeaterScheduleState;
emit(WaterHeaterScheduleState(
scheduleType: currentState.scheduleType,
hours: currentState.hours,
minutes: currentState.minutes,
isActive: false,
));
}
}
FutureOr<void> _controlWaterHeater(
ToggleWaterHeaterEvent event, Emitter<WaterHeaterState> emit) async {
final oldValue = deviceStatus.heaterSwitch;
_updateLocalValue(event.isOn);
emit(WaterHeaterToggleState(isOn: event.isOn));
await _runDebounce(
deviceId: event.deviceId,
value: event.isOn,
oldValue: oldValue,
emit: emit,
);
}
Future<void> _runDebounce({
required String deviceId,
required bool value,
required bool oldValue,
required Emitter<WaterHeaterState> emit,
}) async {
if (_timer != null) {
_timer!.cancel();
}
_timer = Timer(const Duration(milliseconds: 500), () async {
try {
//// TODO: implement control
// final status = await DevicesManagementApi().deviceControl(
// deviceId, Status(value: value, code: 'heaterSwitch'));
// if (!status) {
// _revertValueAndEmit(deviceId, oldValue, emit);
// }
} catch (e) {
_revertValueAndEmit(deviceId, oldValue, emit);
}
});
}
void _revertValueAndEmit(
String deviceId, bool oldValue, Emitter<WaterHeaterState> emit) {
_updateLocalValue(oldValue);
emit(WaterHeaterToggleState(isOn: oldValue));
}
void _updateLocalValue(bool value) {
deviceStatus = deviceStatus.copyWith(heaterSwitch: value);
}
FutureOr<void> _fetchWaterHeaterStatus(
WaterHeaterFetchStatusEvent event, Emitter<WaterHeaterState> emit) async {
emit(WaterHeaterLoadingState());
try {
// final status =
// await DevicesManagementApi().getDeviceStatus(event.deviceId);
// deviceStatus =
// WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
final List<Status> fakeStatusList = [
Status(code: 'switch', value: true),
Status(code: 'schedule_mode', value: 'countdown'),
Status(code: 'countdown_hours', value: 6),
Status(code: 'countdown_minutes', value: 23),
];
final fakeWaterHeaterStatus =
WaterHeaterStatusModel.fromJson(event.deviceId, fakeStatusList);
emit(WaterHeaterDeviceStatusLoaded(fakeWaterHeaterStatus));
} catch (e) {
emit(WaterHeaterFailedState(error: e.toString()));
}
}
@override
Future<void> close() {
_timer?.cancel();
return super.close();
}
}

View File

@ -0,0 +1,49 @@
part of 'water_heater_bloc.dart';
sealed class WaterHeaterEvent extends Equatable {
const WaterHeaterEvent();
@override
List<Object?> get props => [];
}
final class ToggleWaterHeaterEvent extends WaterHeaterEvent {
final bool isOn;
final String deviceId;
const ToggleWaterHeaterEvent({required this.isOn, required this.deviceId});
@override
List<Object?> get props => [isOn];
}
final class UpdateScheduleEvent extends WaterHeaterEvent {
final ScheduleType scheduleType;
final int hours;
final int minutes;
const UpdateScheduleEvent(this.scheduleType, this.hours, this.minutes);
@override
List<Object?> get props => [scheduleType, hours, minutes];
}
final class StopScheduleEvent extends WaterHeaterEvent {}
class WaterHeaterFetchStatusEvent extends WaterHeaterEvent {
final String deviceId;
const WaterHeaterFetchStatusEvent(this.deviceId);
@override
List<Object?> get props => [deviceId];
}
class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
final String deviceId;
const WaterHeaterFetchBatchStatusEvent(this.deviceId);
@override
List<Object?> get props => [deviceId];
}

View File

@ -0,0 +1,76 @@
part of 'water_heater_bloc.dart';
enum ScheduleType { countdown, schedule, circulate, inching }
sealed class WaterHeaterState extends Equatable {
const WaterHeaterState();
@override
List<Object?> get props => [];
}
final class WaterHeaterInitial extends WaterHeaterState {}
final class WaterHeaterToggleState extends WaterHeaterState {
final bool isOn;
const WaterHeaterToggleState({required this.isOn});
@override
List<Object?> get props => [isOn];
}
final class WaterHeaterScheduleState extends WaterHeaterState {
final ScheduleType scheduleType;
final int hours;
final int minutes;
final bool isActive;
const WaterHeaterScheduleState({
required this.scheduleType,
required this.hours,
required this.minutes,
required this.isActive,
});
@override
List<Object?> get props => [scheduleType, hours, minutes, isActive];
}
final class WaterHeaterDeviceStatusLoaded extends WaterHeaterState {
final WaterHeaterStatusModel status;
const WaterHeaterDeviceStatusLoaded(this.status);
@override
List<Object?> get props => [status];
}
final class WaterHeaterBatchStatusLoaded extends WaterHeaterState {
final WaterHeaterStatusModel status;
const WaterHeaterBatchStatusLoaded(this.status);
@override
List<Object?> get props => [status];
}
final class WaterHeaterFailedState extends WaterHeaterState {
final String error;
const WaterHeaterFailedState({required this.error});
@override
List<Object?> get props => [error];
}
final class WaterHeaterBatchFailedState extends WaterHeaterState {
final String error;
const WaterHeaterBatchFailedState({required this.error});
@override
List<Object?> get props => [error];
}
final class WaterHeaterLoadingState extends WaterHeaterState {}

View File

@ -0,0 +1,83 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
enum ScheduleModes { countdown, schedule, circulate, inching }
class WaterHeaterStatusModel {
final String uuid;
final bool heaterSwitch;
final String scheduleModeString;
final int countdownHours;
final int countdownMinutes;
final ScheduleModes scheduleMode;
WaterHeaterStatusModel({
required this.uuid,
required this.heaterSwitch,
required this.scheduleModeString,
required this.countdownHours,
required this.countdownMinutes,
}) : scheduleMode = getScheduleMode(scheduleModeString);
factory WaterHeaterStatusModel.fromJson(String id, List<Status> jsonList) {
late bool heaterSwitch;
late String scheduleMode;
late int countdownHours;
late int countdownMinutes;
for (var status in jsonList) {
switch (status.code) {
case 'switch':
heaterSwitch = status.value ?? false;
break;
case 'schedule_mode':
scheduleMode = status.value ?? 'countdown';
break;
case 'countdown_hours':
countdownHours = status.value ?? 0;
break;
case 'countdown_minutes':
countdownMinutes = status.value ?? 0;
break;
}
}
return WaterHeaterStatusModel(
uuid: id,
heaterSwitch: heaterSwitch,
scheduleModeString: scheduleMode,
countdownHours: countdownHours,
countdownMinutes: countdownMinutes,
);
}
WaterHeaterStatusModel copyWith({
String? uuid,
bool? heaterSwitch,
String? scheduleModeString,
int? countdownHours,
int? countdownMinutes,
}) {
return WaterHeaterStatusModel(
uuid: uuid ?? this.uuid,
heaterSwitch: heaterSwitch ?? this.heaterSwitch,
scheduleModeString: scheduleModeString ?? this.scheduleModeString,
countdownHours: countdownHours ?? this.countdownHours,
countdownMinutes: countdownMinutes ?? this.countdownMinutes,
);
}
static ScheduleModes getScheduleMode(String value) {
switch (value) {
case 'countdown':
return ScheduleModes.countdown;
case 'schedule':
return ScheduleModes.schedule;
case 'circulate':
return ScheduleModes.circulate;
case 'inching':
return ScheduleModes.inching;
default:
return ScheduleModes.countdown;
}
}
}

View File

@ -0,0 +1,73 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart';
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class WaterHeaterDeviceControl extends StatelessWidget
with HelperResponsiveLayout {
const WaterHeaterDeviceControl({super.key, required this.device});
final AllDevicesModel device;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
WaterHeaterBloc()..add(WaterHeaterFetchStatusEvent(device.uuid!)),
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
builder: (context, state) {
if (state is WaterHeaterLoadingState) {
return const Center(child: CircularProgressIndicator());
} else if (state is WaterHeaterDeviceStatusLoaded) {
return _buildStatusControls(context, state.status);
} else if (state is WaterHeaterFailedState ||
state is WaterHeaterBatchFailedState) {
return const Center(child: Text('Error fetching status'));
} else {
return const Center(child: CircularProgressIndicator());
}
},
));
}
Widget _buildStatusControls(
BuildContext context, WaterHeaterStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
const SizedBox(),
ToggleWidget(
deviceId: device.uuid!,
code: 'water_heater',
value: false,
label: 'Water Heater',
onChange: (value) {
context.read<WaterHeaterBloc>().add(ToggleWaterHeaterEvent(
deviceId: device.uuid!,
isOn: value,
));
},
),
],
);
}
}