push ac batch control

This commit is contained in:
ashrafzarkanisala
2024-09-18 12:27:00 +03:00
parent 7c28012d79
commit abb0a58468
26 changed files with 516 additions and 66 deletions

View File

@ -14,13 +14,14 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
Timer? _timer; Timer? _timer;
AcBloc({required this.deviceId}) : super(AcsInitialState()) { AcBloc({required this.deviceId}) : super(AcsInitialState()) {
on<AcFetchDeviceStatus>(_onFetchAcStatus); on<AcFetchDeviceStatusEvent>(_onFetchAcStatus);
on<AcFetchBatchStatus>(_onFetchAcBatchStatus); on<AcFetchBatchStatusEvent>(_onFetchAcBatchStatus);
on<AcControl>(_onAcControl); on<AcControlEvent>(_onAcControl);
on<AcBatchControlEvent>(_onAcBatchControl);
} }
FutureOr<void> _onFetchAcStatus( FutureOr<void> _onFetchAcStatus(
AcFetchDeviceStatus event, Emitter<AcsState> emit) async { AcFetchDeviceStatusEvent event, Emitter<AcsState> emit) async {
emit(AcsLoadingState()); emit(AcsLoadingState());
try { try {
final status = final status =
@ -32,7 +33,8 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
} }
} }
FutureOr<void> _onAcControl(AcControl event, Emitter<AcsState> emit) async { FutureOr<void> _onAcControl(
AcControlEvent event, Emitter<AcsState> emit) async {
final oldValue = _getValueByCode(event.code); final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value, emit); _updateLocalValue(event.code, event.value, emit);
@ -40,6 +42,7 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
emit(ACStatusLoaded(deviceStatus)); emit(ACStatusLoaded(deviceStatus));
await _runDebounce( await _runDebounce(
isBatch: false,
deviceId: event.deviceId, deviceId: event.deviceId,
code: event.code, code: event.code,
value: event.value, value: event.value,
@ -49,27 +52,43 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
} }
Future<void> _runDebounce({ Future<void> _runDebounce({
required String deviceId, required dynamic deviceId,
required String code, required String code,
required dynamic value, required dynamic value,
required dynamic oldValue, required dynamic oldValue,
required Emitter<AcsState> emit, required Emitter<AcsState> emit,
required bool isBatch,
}) async { }) async {
late String id;
if (deviceId is List) {
id = deviceId.first;
} else {
id = deviceId;
}
if (_timer != null) { if (_timer != null) {
_timer!.cancel(); _timer!.cancel();
} }
_timer = Timer(const Duration(seconds: 1), () async { _timer = Timer(const Duration(seconds: 1), () async {
try { try {
final response = await DevicesManagementApi() late bool response;
.deviceControl(deviceId, Status(code: code, value: value)); if (isBatch) {
response = await DevicesManagementApi()
.deviceBatchControl(deviceId, code, value);
} else {
response = await DevicesManagementApi()
.deviceControl(deviceId, Status(code: code, value: value));
}
if (!response) { if (!response) {
_revertValueAndEmit(deviceId, code, oldValue, emit); _revertValueAndEmit(id, code, oldValue, emit);
} }
} catch (e) { } catch (e) {
if (e is DioException && e.response != null) { if (e is DioException && e.response != null) {
debugPrint('Error response: ${e.response?.data}'); debugPrint('Error response: ${e.response?.data}');
} }
_revertValueAndEmit(deviceId, code, oldValue, emit); _revertValueAndEmit(id, code, oldValue, emit);
} }
}); });
} }
@ -78,7 +97,6 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
String deviceId, String code, dynamic oldValue, Emitter<AcsState> emit) { String deviceId, String code, dynamic oldValue, Emitter<AcsState> emit) {
_updateLocalValue(code, oldValue, emit); _updateLocalValue(code, oldValue, emit);
emit(ACStatusLoaded(deviceStatus)); emit(ACStatusLoaded(deviceStatus));
emit(const AcsFailedState(error: 'Failed to control the device.'));
} }
void _updateLocalValue(String code, dynamic value, Emitter<AcsState> emit) { void _updateLocalValue(String code, dynamic value, Emitter<AcsState> emit) {
@ -136,15 +154,34 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
} }
FutureOr<void> _onFetchAcBatchStatus( FutureOr<void> _onFetchAcBatchStatus(
AcFetchBatchStatus event, Emitter<AcsState> emit) async { AcFetchBatchStatusEvent event, Emitter<AcsState> emit) async {
emit(AcsLoadingState()); emit(AcsLoadingState());
try { try {
final status = final status =
await DevicesManagementApi().getDeviceStatus(event.deviceId); await DevicesManagementApi().getBatchStatus(event.devicesIds);
deviceStatus = AcStatusModel.fromJson(event.deviceId, status.status); deviceStatus =
AcStatusModel.fromJson(event.devicesIds.first, status.status);
emit(ACStatusLoaded(deviceStatus)); emit(ACStatusLoaded(deviceStatus));
} catch (e) { } catch (e) {
emit(AcsFailedState(error: e.toString())); emit(AcsFailedState(error: e.toString()));
} }
} }
FutureOr<void> _onAcBatchControl(
AcBatchControlEvent event, Emitter<AcsState> emit) async {
final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value, emit);
emit(ACStatusLoaded(deviceStatus));
await _runDebounce(
isBatch: true,
deviceId: event.devicesIds,
code: event.code,
value: event.value,
oldValue: oldValue,
emit: emit,
);
}
} }

View File

@ -7,30 +7,30 @@ sealed class AcsEvent extends Equatable {
List<Object> get props => []; List<Object> get props => [];
} }
class AcFetchDeviceStatus extends AcsEvent { class AcFetchDeviceStatusEvent extends AcsEvent {
final String deviceId; final String deviceId;
const AcFetchDeviceStatus(this.deviceId); const AcFetchDeviceStatusEvent(this.deviceId);
@override @override
List<Object> get props => [deviceId]; List<Object> get props => [deviceId];
} }
class AcFetchBatchStatus extends AcsEvent { class AcFetchBatchStatusEvent extends AcsEvent {
final String deviceId; final List<String> devicesIds;
const AcFetchBatchStatus(this.deviceId); const AcFetchBatchStatusEvent(this.devicesIds);
@override @override
List<Object> get props => [deviceId]; List<Object> get props => [devicesIds];
} }
class AcControl extends AcsEvent { class AcControlEvent extends AcsEvent {
final String deviceId; final String deviceId;
final String code; final String code;
final dynamic value; final dynamic value;
const AcControl({ const AcControlEvent({
required this.deviceId, required this.deviceId,
required this.code, required this.code,
required this.value, required this.value,
@ -39,3 +39,18 @@ class AcControl extends AcsEvent {
@override @override
List<Object> get props => [deviceId, code, value]; List<Object> get props => [deviceId, code, value];
} }
class AcBatchControlEvent extends AcsEvent {
final List<String> devicesIds;
final String code;
final dynamic value;
const AcBatchControlEvent({
required this.devicesIds,
required this.code,
required this.value,
});
@override
List<Object> get props => [devicesIds, code, value];
}

View File

@ -22,6 +22,16 @@ class ACStatusLoaded extends AcsState {
List<Object> get props => [status, timestamp]; List<Object> get props => [status, timestamp];
} }
class AcBatchStatusLoaded extends AcsState {
final AcStatusModel status;
final DateTime timestamp;
AcBatchStatusLoaded(this.status) : timestamp = DateTime.now();
@override
List<Object> get props => [status, timestamp];
}
class AcsFailedState extends AcsState { class AcsFailedState extends AcsState {
final String error; final String error;

View File

@ -40,16 +40,16 @@ class AcStatusModel {
acSwitch = status.value ?? false; acSwitch = status.value ?? false;
break; break;
case 'mode': case 'mode':
mode = status.value ?? 'cold'; // default to 'cold' if null mode = status.value ?? 'cold';
break; break;
case 'temp_set': case 'temp_set':
tempSet = status.value ?? 210; // default value if null tempSet = status.value ?? 210;
break; break;
case 'temp_current': case 'temp_current':
currentTemp = status.value ?? 210; // default value if null currentTemp = status.value ?? 210;
break; break;
case 'level': case 'level':
fanSpeeds = status.value ?? 'low'; // default value if null fanSpeeds = status.value ?? 'low';
break; break;
case 'child_lock': case 'child_lock':
childLock = status.value ?? false; childLock = status.value ?? false;

View File

@ -3,12 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_mode.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_toggle.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/current_temp.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/fan_speed.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; 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';
@ -25,7 +25,7 @@ class AcDeviceBatchControlView extends StatelessWidget
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
return BlocProvider( return BlocProvider(
create: (context) => AcBloc(deviceId: devicesIds.first) create: (context) => AcBloc(deviceId: devicesIds.first)
..add(AcFetchBatchStatus(devicesIds.first)), ..add(AcFetchBatchStatusEvent(devicesIds)),
child: BlocBuilder<AcBloc, AcsState>( child: BlocBuilder<AcBloc, AcsState>(
builder: (context, state) { builder: (context, state) {
if (state is ACStatusLoaded) { if (state is ACStatusLoaded) {
@ -44,34 +44,49 @@ class AcDeviceBatchControlView extends StatelessWidget
mainAxisSpacing: 12, mainAxisSpacing: 12,
), ),
children: [ children: [
AcToggle( ToggleWidget(
value: state.status.acSwitch,
code: 'switch',
deviceId: devicesIds.first, deviceId: devicesIds.first,
code: 'switch',
value: state.status.acSwitch,
label: 'ThermoState',
onChange: (value) {
context.read<AcBloc>().add(AcBatchControlEvent(
devicesIds: devicesIds,
code: 'switch',
value: value,
));
},
), ),
CurrentTemp( BatchCurrentTemp(
currentTemp: state.status.currentTemp, currentTemp: state.status.currentTemp,
tempSet: state.status.tempSet, tempSet: state.status.tempSet,
code: 'temp_set', code: 'temp_set',
deviceId: devicesIds.first, devicesIds: devicesIds,
), ),
AcMode( BatchAcMode(
value: state.status.acMode, value: state.status.acMode,
code: 'mode', code: 'mode',
deviceId: devicesIds.first, devicesIds: devicesIds,
), ),
FanSpeedControl( BatchFanSpeedControl(
value: state.status.acFanSpeed, value: state.status.acFanSpeed,
code: 'level', code: 'level',
deviceId: devicesIds.first, devicesIds: devicesIds,
), ),
AcToggle( ToggleWidget(
value: state.status.childLock,
code: 'child_lock',
deviceId: devicesIds.first, deviceId: devicesIds.first,
description: 'Child Lock', code: 'child_lock',
value: state.status.childLock,
label: 'Child Lock',
icon: icon:
state.status.childLock ? Assets.childLock : Assets.unlock, state.status.childLock ? Assets.childLock : Assets.unlock,
onChange: (value) {
context.read<AcBloc>().add(AcBatchControlEvent(
devicesIds: devicesIds,
code: 'child_lock',
value: value,
));
},
), ),
FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5), FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5),
FactoryResetWidget(deviceId: devicesIds.first), FactoryResetWidget(deviceId: devicesIds.first),

View File

@ -23,7 +23,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
return BlocProvider( return BlocProvider(
create: (context) => AcBloc(deviceId: device.uuid!) create: (context) => AcBloc(deviceId: device.uuid!)
..add(AcFetchDeviceStatus(device.uuid!)), ..add(AcFetchDeviceStatusEvent(device.uuid!)),
child: BlocBuilder<AcBloc, AcsState>( child: BlocBuilder<AcBloc, AcsState>(
builder: (context, state) { builder: (context, state) {
if (state is ACStatusLoaded) { if (state is ACStatusLoaded) {

View File

@ -0,0 +1,82 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
class BatchAcMode extends StatelessWidget {
const BatchAcMode({
super.key,
required this.value,
required this.code,
required this.devicesIds,
});
final TempModes value;
final String code;
final List<String> devicesIds;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider),
),
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_buildIconContainer(context, TempModes.cold, Assets.freezing,
value == TempModes.cold),
_buildIconContainer(
context, TempModes.hot, Assets.acSun, value == TempModes.hot),
_buildIconContainer(context, TempModes.wind, Assets.acAirConditioner,
value == TempModes.wind),
],
),
);
}
Widget _buildIconContainer(
BuildContext context, TempModes mode, String assetPath, bool isSelected) {
return Flexible(
child: GestureDetector(
onTap: () {
context.read<AcBloc>().add(
AcBatchControlEvent(
devicesIds: devicesIds,
code: code,
value: mode.name,
),
);
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: ColorsManager.whiteColors,
border: Border.all(
color: isSelected ? Colors.blue : Colors.transparent,
width: 2.0,
),
),
margin: const EdgeInsets.symmetric(horizontal: 4),
padding: const EdgeInsets.all(4),
child: ClipOval(
child: SvgPicture.asset(
assetPath,
fit: BoxFit.contain,
),
),
),
),
);
}
}

View File

@ -0,0 +1,138 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart';
import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
class BatchCurrentTemp extends StatefulWidget {
const BatchCurrentTemp({
super.key,
required this.code,
required this.devicesIds,
required this.currentTemp,
required this.tempSet,
});
final String code;
final List<String> devicesIds;
final int currentTemp;
final int tempSet;
@override
State<BatchCurrentTemp> createState() => _CurrentTempState();
}
class _CurrentTempState extends State<BatchCurrentTemp> {
late double _adjustedValue;
Timer? _debounce;
@override
void initState() {
super.initState();
_adjustedValue = _initialAdjustedValue(widget.tempSet);
}
double _initialAdjustedValue(dynamic value) {
if (value is int || value is double) {
double doubleValue = value.toDouble();
return doubleValue > 99 ? doubleValue / 10 : doubleValue;
} else {
throw ArgumentError('Invalid value type: Expected int or double');
}
}
void _onValueChanged(double newValue) {
if (_debounce?.isActive ?? false) {
_debounce?.cancel();
}
_debounce = Timer(const Duration(milliseconds: 500), () {
context.read<AcBloc>().add(
AcBatchControlEvent(
devicesIds: widget.devicesIds,
code: widget.code,
value: (newValue * 10).toInt(),
),
);
});
}
@override
void dispose() {
_debounce?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider),
),
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Current Temperature',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.grey),
),
const SizedBox(
height: 5,
),
Row(
children: [
Text(
(widget.currentTemp > 99
? widget.currentTemp / 10
: widget.currentTemp)
.toString(),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.grey),
),
const CelsiusSymbol(
color: Colors.grey,
)
],
),
],
),
const Spacer(),
IncrementDecrementWidget(
value: _adjustedValue.toString(),
description: '°C',
descriptionColor: ColorsManager.dialogBlueTitle,
onIncrement: () {
if (_adjustedValue < 30) {
setState(() {
_adjustedValue++;
});
_onValueChanged(_adjustedValue);
}
},
onDecrement: () {
if (_adjustedValue > 20) {
setState(() {
_adjustedValue--;
});
_onValueChanged(_adjustedValue);
}
}),
],
),
);
}
}

View File

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
class BatchFanSpeedControl extends StatelessWidget {
const BatchFanSpeedControl({
super.key,
required this.value,
required this.code,
required this.devicesIds,
});
final FanSpeeds value;
final String code;
final List<String> devicesIds;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider),
),
padding: const EdgeInsets.all(8),
child: Column(
children: [
Wrap(
runSpacing: 8,
spacing: 8,
children: [
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto,
value == FanSpeeds.auto),
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow,
value == FanSpeeds.low),
],
),
Wrap(
runSpacing: 8,
spacing: 8,
children: [
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle,
value == FanSpeeds.middle),
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh,
value == FanSpeeds.high),
],
)
],
),
);
}
Widget _buildIconContainer(BuildContext context, FanSpeeds speed,
String assetPath, bool isSelected) {
return GestureDetector(
onTap: () {
context.read<AcBloc>().add(
AcBatchControlEvent(
devicesIds: devicesIds,
code: code,
value: speed.name,
),
);
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: ColorsManager.whiteColors,
border: Border.all(
color: isSelected ? Colors.blue : Colors.transparent,
width: 2.0,
),
),
padding: const EdgeInsets.all(8),
child: ClipOval(
child: SvgPicture.asset(
assetPath,
fit: BoxFit.contain,
),
),
),
);
}
}

View File

@ -49,7 +49,7 @@ class AcMode extends StatelessWidget {
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
context.read<AcBloc>().add( context.read<AcBloc>().add(
AcControl( AcControlEvent(
deviceId: deviceId, deviceId: deviceId,
code: code, code: code,
value: mode.name, value: mode.name,

View File

@ -57,7 +57,7 @@ class AcToggle extends StatelessWidget {
value: value, value: value,
onChanged: (newValue) { onChanged: (newValue) {
context.read<AcBloc>().add( context.read<AcBloc>().add(
AcControl( AcControlEvent(
deviceId: deviceId, deviceId: deviceId,
code: code, code: code,
value: newValue, value: newValue,

View File

@ -50,7 +50,7 @@ class _CurrentTempState extends State<CurrentTemp> {
} }
_debounce = Timer(const Duration(milliseconds: 500), () { _debounce = Timer(const Duration(milliseconds: 500), () {
context.read<AcBloc>().add( context.read<AcBloc>().add(
AcControl( AcControlEvent(
deviceId: widget.deviceId, deviceId: widget.deviceId,
code: widget.code, code: widget.code,
value: (newValue * 10).toInt(), value: (newValue * 10).toInt(),

View File

@ -60,7 +60,7 @@ class FanSpeedControl extends StatelessWidget {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
context.read<AcBloc>().add( context.read<AcBloc>().add(
AcControl( AcControlEvent(
deviceId: deviceId, deviceId: deviceId,
code: code, code: code,
value: speed.name, value: speed.name,

View File

@ -124,7 +124,7 @@ class MainDoorSensorBloc
Emitter<MainDoorSensorState> emit) async { Emitter<MainDoorSensorState> emit) async {
emit(MainDoorSensorLoadingState()); emit(MainDoorSensorLoadingState());
try { try {
final reports = await DevicesManagementApi.getDeviceReports( final reports = await DevicesManagementApi.getDeviceReportsByDate(
event.deviceId, event.code, event.from, event.to); event.deviceId, event.code, event.from, event.to);
emit(MainDoorSensorReportLoaded(reports)); emit(MainDoorSensorReportLoaded(reports));
} catch (e) { } catch (e) {

View File

@ -76,13 +76,7 @@ class MainDoorSensorControlView extends StatelessWidget
IconNameStatusContainer( IconNameStatusContainer(
name: status.doorContactState ? 'Open' : 'Close', name: status.doorContactState ? 'Open' : 'Close',
icon: Assets.mainDoor, icon: Assets.mainDoor,
onTap: () { onTap: () {},
context.read<MainDoorSensorBloc>().add(MainDoorSensorControl(
deviceId: device.uuid!,
code: 'doorcontact_state',
value: !status.doorContactState,
));
},
status: status.doorContactState, status: status.doorContactState,
textColor: ColorsManager.red, textColor: ColorsManager.red,
paddingAmount: 8, paddingAmount: 8,

View File

@ -6,7 +6,7 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_lig
import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.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';
class WallLightBatchControlView extends StatelessWidget class WallLightBatchControlView extends StatelessWidget

View File

@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_lig
import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_event.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_state.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_state.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.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';
class WallLightDeviceControl extends StatelessWidget class WallLightDeviceControl extends StatelessWidget

View File

@ -63,7 +63,8 @@ class ReportsTable extends StatelessWidget {
TableCellWidget(value: time), TableCellWidget(value: time),
hideValueShowDescription == true hideValueShowDescription == true
? TableCellWidget( ? TableCellWidget(
value: mainDoorSensor == true value: (mainDoorSensor != null &&
mainDoorSensor == true)
? data.value == 'true' ? data.value == 'true'
? 'Open' ? 'Open'
: 'Close' : 'Close'

View File

@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.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';
class LivingRoomBatchControlsView extends StatelessWidget class LivingRoomBatchControlsView extends StatelessWidget

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.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';
class LivingRoomDeviceControlsView extends StatelessWidget class LivingRoomDeviceControlsView extends StatelessWidget

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart';
import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart';

View File

@ -1,6 +1,6 @@
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_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart';
import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart';

View File

@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.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/shared/device_controls_container.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/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/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/device_managment/water_heater/models/water_heater_status_model.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';

View File

@ -65,6 +65,31 @@ class DevicesManagementApi {
} }
} }
Future<bool> deviceBatchControl(
List<String> uuids, String code, dynamic value) async {
try {
final body = {
'devicesUuid': uuids,
'code': code,
'value': value,
};
final response = await HTTPService().post(
path: ApiEndpoints.deviceBatchControl,
body: body,
showServerMessage: true,
expectedResponseModel: (json) {
return json['success'] ?? false;
},
);
return response;
} catch (e) {
debugPrint('Error fetching $e');
return false;
}
}
static Future<List<DeviceModel>> getDevicesByGatewayId( static Future<List<DeviceModel>> getDevicesByGatewayId(
String gatewayId) async { String gatewayId) async {
final response = await HTTPService().get( final response = await HTTPService().get(
@ -95,7 +120,23 @@ class DevicesManagementApi {
return response; return response;
} }
static Future<DeviceReport> getDeviceReports(String uuid, String code, static Future<DeviceReport> getDeviceReports(
String uuid,
String code,
) async {
final response = await HTTPService().get(
path: ApiEndpoints.getDeviceLogs
.replaceAll('{uuid}', uuid)
.replaceAll('{code}', code),
showServerMessage: false,
expectedResponseModel: (json) {
return DeviceReport.fromJson(json);
},
);
return response;
}
static Future<DeviceReport> getDeviceReportsByDate(String uuid, String code,
[String? from, String? to]) async { [String? from, String? to]) async {
final response = await HTTPService().get( final response = await HTTPService().get(
path: ApiEndpoints.getDeviceLogsByDate path: ApiEndpoints.getDeviceLogsByDate
@ -110,4 +151,28 @@ class DevicesManagementApi {
); );
return response; return response;
} }
Future<DeviceStatus> getBatchStatus(List<String> uuids) async {
try {
final queryParameters = {
'devicesUuid': uuids.join(','),
};
final response = await HTTPService().get(
path: ApiEndpoints.getBatchStatus,
queryParameters: queryParameters,
showServerMessage: true,
expectedResponseModel: (json) {
return DeviceStatus.fromJson(json['status']);
},
);
return response;
} catch (e) {
debugPrint('Error fetching $e');
return DeviceStatus(
productUuid: '',
productType: '',
status: [],
);
}
}
} }

View File

@ -28,8 +28,10 @@ abstract class ApiEndpoints {
static const String getAllDevices = '/device'; static const String getAllDevices = '/device';
static const String getDeviceStatus = '/device/{uuid}/functions/status'; static const String getDeviceStatus = '/device/{uuid}/functions/status';
static const String getBatchStatus = '/device/status/batch';
static const String deviceControl = '/device/{uuid}/control'; static const String deviceControl = '/device/{uuid}/control';
static const String deviceBatchControl = '/device/control/batch';
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices'; static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
static const String openDoorLock = '/door-lock/open/{doorLockUuid}'; static const String openDoorLock = '/door-lock/open/{doorLockUuid}';