Browse Source

control device

master
daivph 5 years ago
parent
commit
d65af388a9
9 changed files with 482 additions and 3 deletions
  1. +31
    -0
      lib/custom_model/Device.dart
  2. +4
    -0
      lib/data/api/rest_client.dart
  3. +20
    -0
      lib/data/api/rest_client.g.dart
  4. +7
    -0
      lib/data/repository/repository.dart
  5. +55
    -0
      lib/presentation/screens/control_device/bloc/device_bloc.dart
  6. +22
    -0
      lib/presentation/screens/control_device/bloc/device_event.dart
  7. +33
    -0
      lib/presentation/screens/control_device/bloc/device_state.dart
  8. +43
    -3
      lib/presentation/screens/control_device/sc_control_device.dart
  9. +267
    -0
      lib/presentation/screens/control_device/widget_device_list.dart

+ 31
- 0
lib/custom_model/Device.dart View File

class Device {
int id;
String name;
String status;
String location;

Device({this.id, this.name, this.status, this.location});

Device.clone(Device device) {
this.id = device.id;
this.name = device.name;
this.status = device.status;
this.location = device.location;
}

Device.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
status = json['status'];
location = json['location'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['status'] = this.status;
data['location'] = this.location;
return data;
}
}

+ 4
- 0
lib/data/api/rest_client.dart View File

import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:farm_tpf/custom_model/CropPlot.dart'; import 'package:farm_tpf/custom_model/CropPlot.dart';
import 'package:farm_tpf/custom_model/Device.dart';
import 'package:farm_tpf/custom_model/account.dart'; import 'package:farm_tpf/custom_model/account.dart';
import 'package:farm_tpf/custom_model/password.dart'; import 'package:farm_tpf/custom_model/password.dart';
import 'package:farm_tpf/custom_model/user.dart'; import 'package:farm_tpf/custom_model/user.dart';


@PUT("/api/tb-crops") @PUT("/api/tb-crops")
Future<void> updateCrop(@Body() TbCropDTO crop); Future<void> updateCrop(@Body() TbCropDTO crop);
//Device
@GET("/api/listDeviceOfUserCustomers")
Future<List<Device>> getDevices();
} }

+ 20
- 0
lib/data/api/rest_client.g.dart View File

data: _data); data: _data);
return null; return null;
} }

@override
getDevices() async {
const _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _data = <String, dynamic>{};
final Response<List<dynamic>> _result = await _dio.request(
'/api/listDeviceOfUserCustomers',
queryParameters: queryParameters,
options: RequestOptions(
method: 'GET',
headers: <String, dynamic>{},
extra: _extra,
baseUrl: baseUrl),
data: _data);
var value = _result.data
.map((dynamic i) => Device.fromJson(i as Map<String, dynamic>))
.toList();
return value;
}
} }

+ 7
- 0
lib/data/repository/repository.dart View File



import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:farm_tpf/custom_model/CropPlot.dart'; import 'package:farm_tpf/custom_model/CropPlot.dart';
import 'package:farm_tpf/custom_model/Device.dart';
import 'package:farm_tpf/custom_model/user.dart'; import 'package:farm_tpf/custom_model/user.dart';
import 'package:farm_tpf/custom_model/user_request.dart'; import 'package:farm_tpf/custom_model/user_request.dart';
import 'package:farm_tpf/data/api/app_exception.dart'; import 'package:farm_tpf/data/api/app_exception.dart';
onError(AppException.handleError(e)); onError(AppException.handleError(e));
} }
} }

//Device
Future<List<Device>> getDevices() {
final client = RestClient(dio);
return client.getDevices();
}
} }

+ 55
- 0
lib/presentation/screens/control_device/bloc/device_bloc.dart View File

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/Device.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:meta/meta.dart';

part 'device_event.dart';
part 'device_state.dart';

class DeviceBloc extends Bloc<DeviceEvent, DeviceState> {
final Repository repository;

DeviceBloc({@required this.repository}) : super(DeviceInitial());

@override
Stream<DeviceState> mapEventToState(
DeviceEvent event,
) async* {
if (event is OpenScreen) {
yield* _mapOpenScreenToState();
} else if (event is ControlDevice) {
yield* _mapControlDeviceToState(
event.currentDevices, event.updatedDeviceId);
}
}

Stream<DeviceState> _mapOpenScreenToState() async* {
yield DisplayDevice.loading();
try {
List<Device> devices = new List<Device>();
final response = await repository.getDevices();
devices = response;
devices.sort((a, b) => (a.id).compareTo(b.id));
yield DisplayDevice.data(devices);
} catch (e) {
yield DisplayDevice.error(AppException.handleError(e));
}
}

Stream<DeviceState> _mapControlDeviceToState(
List<Device> currentDevices, int updatedDeviceId) async* {
List<Device> devices = new List<Device>();
currentDevices.forEach((device) {
if (device.id == updatedDeviceId) {
var updatedStatus = device.status == "1" ? "0" : "1";
device.status = updatedStatus;
}
devices.add(Device.clone(device));
});
yield DisplayDevice.data(devices);
}
}

+ 22
- 0
lib/presentation/screens/control_device/bloc/device_event.dart View File

part of 'device_bloc.dart';

abstract class DeviceEvent extends Equatable {
const DeviceEvent();

@override
List<Object> get props => [];
}

class OpenScreen extends DeviceEvent {
OpenScreen();

@override
List<Object> get props => [];
}

class ControlDevice extends DeviceEvent {
final List<Device> currentDevices;
final int updatedDeviceId;
ControlDevice(
{@required this.currentDevices, @required this.updatedDeviceId});
}

+ 33
- 0
lib/presentation/screens/control_device/bloc/device_state.dart View File

part of 'device_bloc.dart';

abstract class DeviceState extends Equatable {
const DeviceState();

@override
List<Object> get props => [];
}

class DeviceInitial extends DeviceState {}

class DisplayDevice extends DeviceState {
List<Device> devices;
bool loading;
String msg;

DisplayDevice({this.devices, this.loading, this.msg});

factory DisplayDevice.loading() {
return DisplayDevice(devices: null, loading: true, msg: null);
}

factory DisplayDevice.data(List<Device> data) {
return DisplayDevice(devices: data, loading: false, msg: null);
}

factory DisplayDevice.error(String msg) {
return DisplayDevice(devices: null, loading: false, msg: msg);
}

@override
List<Object> get props => [devices, loading, msg];
}

+ 43
- 3
lib/presentation/screens/control_device/sc_control_device.dart View File

import 'package:farm_tpf/data/repository/repository.dart';
import 'package:farm_tpf/presentation/screens/control_device/widget_device_list.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'bloc/device_bloc.dart';


class ControlDeviceScreen extends StatefulWidget { class ControlDeviceScreen extends StatefulWidget {
@override @override
} }


class _ControlDeviceScreenState extends State<ControlDeviceScreen> { class _ControlDeviceScreenState extends State<ControlDeviceScreen> {
BuildContext _blocContext;
@override
void initState() {
super.initState();
}

@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_blocContext = context;
return Scaffold( return Scaffold(
appBar: AppBar(
title: Text("Điều khiển thiết bị"),
),
appBar: AppBar(
title: Text("Điều khiển thiết bị"),
),
body: BlocProvider<DeviceBloc>(
create: (context) =>
DeviceBloc(repository: Repository())..add(OpenScreen()),
child: _buildContent()));
}

Widget _buildContent() {
return BlocBuilder<DeviceBloc, DeviceState>(
builder: (context, state) {
if (state is DisplayDevice) {
if (state.loading) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}

if (state.devices != null) {
return Container(
child: WidgetDeviceList(devices: state.devices),
);
}
return Container();
} else {
return Container();
}
},
); );
} }
} }

+ 267
- 0
lib/presentation/screens/control_device/widget_device_list.dart View File

import 'package:dio/dio.dart';
import 'package:farm_tpf/custom_model/Device.dart';
import 'package:farm_tpf/presentation/custom_widgets/widget_loading.dart';
import 'package:farm_tpf/presentation/screens/control_device/bloc/device_bloc.dart';
import 'package:farm_tpf/utils/const_common.dart';
import 'package:farm_tpf/utils/pref.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class WidgetDeviceList extends StatefulWidget {
List<Device> devices;
WidgetDeviceList({@required this.devices});
@override
_WidgetDeviceListState createState() => _WidgetDeviceListState();
}

class _WidgetDeviceListState extends State<WidgetDeviceList> {
List<Device> currentDevices = new List<Device>();
BuildContext _context;
var pref = LocalPref();
var token;
var client;

Future<Null> getSharedPrefs() async {
token = await pref.getString(DATA_CONST.TOKEN_KEY);
var options = BaseOptions(baseUrl: ConstCommon.baseUrl);
options.headers["Authorization"] = "Bearer $token";
client = Dio(options);
}

@override
void initState() {
super.initState();
getSharedPrefs();
}

@override
Widget build(BuildContext context) {
_context = context;
if (widget.devices.isNotEmpty) {
currentDevices = widget.devices;
return widgetDeviceList(
widget.devices.map((show) => ItemDeviceVM.fromDevice(show)).toList(),
_context);
} else {
return Container(
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Text('Không có dữ liệu'),
),
),
);
}
}

Widget widgetDeviceList(List<ItemDeviceVM> items, BuildContext context) {
return Container(
child: GridView.count(
childAspectRatio: (10 / 7),
crossAxisCount: 2,
children: items.map(
(item) {
return _widgetItemDevice(item, context);
},
).toList(),
));
}

Widget _widgetItemDevice(ItemDeviceVM item, BuildContext context) {
return GestureDetector(
onTap: () {
//Navigator.of(context).push(MaterialPageRoute(builder: (context) => DeviceDetail(device: _device,)));
},
child: Card(
margin: EdgeInsets.all(8.0),
shadowColor: Colors.grey,
elevation: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
powerBtn(item, context),
Text(
item.name,
style: TextStyle(
color: Colors.black54,
fontSize: 13,
fontWeight: FontWeight.bold),
overflow: TextOverflow.clip,
maxLines: 2,
textAlign: TextAlign.center,
),
Text(""),
widgetStatus(item)
],
)
]),
));
}

Widget powerBtn(ItemDeviceVM item, BuildContext _context) {
return BlocConsumer<DeviceBloc, DeviceState>(
listener: (context, state) {},
buildWhen: (prev, current) {
return current is DisplayDevice;
},
builder: (context, state) {
if (state is DisplayDevice) {
if (state.loading) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}

if (state.devices != null) {
currentDevices = state.devices;
if (item.status == "0") {
//tat
return IconButton(
icon: Icon(Icons.power_settings_new),
color: Colors.grey,
onPressed: () async {
//bat
_controlSwitchDevice(item, context);
});
} else if (item.status == "1") {
//Bat
return IconButton(
icon: Icon(Icons.power_settings_new),
color: Colors.blue,
onPressed: () async {
//tat
_controlSwitchDevice(item, context);
});
} else {
//loi
return IconButton(
icon: Icon(Icons.power_settings_new),
color: Colors.grey,
onPressed: () {});
}
}
return Container();
} else {
return Container();
}
},
);
}

Widget widgetStatus(ItemDeviceVM item) {
if (item.status == "0") {
return Text(
"Đang Tắt",
style: TextStyle(color: Colors.black54, fontSize: 13),
);
} else if (item.status == "1") {
return Text(
"Đang Bật",
style: TextStyle(color: Colors.green, fontSize: 13),
);
} else {
return Text(
"Không kết nối",
style: TextStyle(color: Colors.red, fontSize: 13),
);
}
}

_controlSwitchDevice(ItemDeviceVM item, BuildContext context) {
//neu status =1 ->tat . Neu Khong = bat
var deviceOnOff = (item.status == "1") ? "0" : "1";
var idDevice = item.id;
var statusDialogView = (item.status == "1") ? "Tắt" : "Bật";
Widget cancelButton = CupertinoDialogAction(
child: Text("Huỷ"),
onPressed: () {
Navigator.of(context).pop();
},
);
Widget continueButton = CupertinoDialogAction(
child: Text("Ok"),
onPressed: () async {
Navigator.of(context).pop();
LoadingDialog.showLoadingDialog(_context);
try {
String urlTurnOff =
"/api/equipment-of-customers-on-off/$idDevice/$deviceOnOff";
var response = await client.put(urlTurnOff);

if (200 <= response.statusCode && response.statusCode < 299) {
BlocProvider.of<DeviceBloc>(_context).add(ControlDevice(
currentDevices: currentDevices, updatedDeviceId: item.id));
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Điều khiển thành công thiết bị ${item.name}'),
Icon(Icons.done),
],
),
backgroundColor: Colors.green,
),
);
}
} catch (error) {
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Điều khiển thiết bị ${item.name} thất bại'),
Icon(Icons.error),
],
),
backgroundColor: Colors.red,
),
);
}
LoadingDialog.hideLoadingDialog(_context);
},
);
CupertinoAlertDialog alert = CupertinoAlertDialog(
title: Text("Điều khiển thiết bị"),
content: Text("$statusDialogView thiết bị ${item.name}?"),
actions: [
cancelButton,
continueButton,
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}

class ItemDeviceVM {
Device device;
num id;
String name;
String status;
String location;

ItemDeviceVM(this.id, this.name, this.status);
ItemDeviceVM.fromDevice(Device device) {
this.device = device;
id = device.id;
name = device.name.toString();
status = device.status;
location = device.location;
}
}

Loading…
Cancel
Save