HomeServer/frontend/lib/devices/plug.dart

266 lines
8 KiB
Dart
Raw Normal View History

2023-10-13 21:33:13 +00:00
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../constants.dart';
2023-10-14 06:41:27 +00:00
import '../states/plug_settings.dart';
2023-10-13 21:33:13 +00:00
import 'devices.dart';
class Plug extends Device {
2023-10-19 14:26:09 +00:00
Plug(this.device_id, this.device_descriptor, this.led_state, this.power_state,
this.power_draw, this.power_control);
2023-10-13 21:33:13 +00:00
final String device_id;
String? device_descriptor;
bool led_state;
bool power_state;
double power_draw;
bool power_control;
2023-10-19 14:26:09 +00:00
static Future<Plug> create(Map<String, dynamic> deviceInfo) async {
final String deviceId = deviceInfo['id'];
final String? deviceDescriptor = deviceInfo['desc'];
final bool powerControl = deviceInfo['toggle'];
2023-10-13 21:33:13 +00:00
final response = await http
2023-10-19 14:26:09 +00:00
.get(Uri.parse("${Constants.BASE_URL}/plug_state/$deviceId"));
2023-10-13 21:33:13 +00:00
if (response.statusCode != 200) {
2023-10-19 14:26:09 +00:00
throw Exception("Failed to fetch plug_state for $deviceId");
2023-10-13 21:33:13 +00:00
}
2023-10-19 14:26:09 +00:00
final Map<String, dynamic> deviceState =
2023-10-13 21:33:13 +00:00
Map.castFrom(jsonDecode(jsonDecode(response.body)));
return Plug(
2023-10-19 14:26:09 +00:00
deviceId,
deviceDescriptor,
deviceState["led"],
deviceState["power"],
deviceState["power_draw"],
powerControl && deviceState["power_draw"] < 15,
2023-10-13 21:33:13 +00:00
);
}
@override
2023-10-14 06:41:27 +00:00
Widget create_widget(BuildContext context) {
2023-10-19 14:26:09 +00:00
const double headerHeight = 40;
const double infoHeight = 30;
const double infoWidth = 60;
const double xOffset = 0.9;
2023-10-13 21:33:13 +00:00
return Table(
2023-10-14 09:33:49 +00:00
border: TableBorder(
borderRadius: BorderRadius.circular(Constants.TABLE_RADIUS)),
2023-10-13 21:33:13 +00:00
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
columnWidths: const {
0: FixedColumnWidth(200.0),
1: FixedColumnWidth(200.0),
},
children: [
TableRow(
decoration: BoxDecoration(
color: Colors.deepPurple[200],
2023-10-14 09:33:49 +00:00
borderRadius: BorderRadius.circular(Constants.TABLE_RADIUS),
2023-10-13 21:33:13 +00:00
),
children: [
SizedBox(
2023-10-19 14:26:09 +00:00
height: headerHeight,
2023-10-13 21:33:13 +00:00
child: Stack(
children: [
Align(
child: Text(
style: const TextStyle(
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
device_descriptor ?? device_id)),
Align(
alignment: Alignment.centerRight,
child: IconButton(
2023-10-14 06:41:27 +00:00
onPressed: () {
Navigator.of(context).pushReplacementNamed(
'/plug_settings',
arguments: PlugSettingsArguments(
2023-10-14 09:33:49 +00:00
device_id, device_descriptor));
2023-10-14 06:41:27 +00:00
},
2023-10-13 21:33:13 +00:00
icon: const Icon(Icons.settings)),
),
],
))
]),
TableRow(children: [
SizedBox(
2023-10-19 14:26:09 +00:00
height: infoHeight,
2023-10-13 21:33:13 +00:00
child: Stack(children: [
const Align(
alignment: Alignment(-0.9, 0.0),
child: Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"LED")),
Align(
2023-10-19 14:26:09 +00:00
alignment: const Alignment(xOffset, 0.0),
2023-10-13 21:33:13 +00:00
child: SizedBox(
2023-10-19 14:26:09 +00:00
width: infoWidth,
2023-10-13 21:33:13 +00:00
child: PlugLed(
device_id: device_id, led_state: led_state))),
]))
]),
TableRow(children: [
SizedBox(
2023-10-19 14:26:09 +00:00
height: infoHeight,
2023-10-13 21:33:13 +00:00
child: Stack(children: [
const Align(
alignment: Alignment(-0.9, 0.0),
child: Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"Power")),
Align(
2023-10-19 14:26:09 +00:00
alignment: const Alignment(xOffset, 0.0),
2023-10-13 21:33:13 +00:00
child: SizedBox(
2023-10-19 14:26:09 +00:00
width: infoWidth,
2023-10-13 21:33:13 +00:00
child: PlugPower(
device_id: device_id,
power_state: power_state,
power_control: power_control))),
]))
]),
TableRow(children: [
SizedBox(
2023-10-19 14:26:09 +00:00
height: infoHeight,
2023-10-13 21:33:13 +00:00
child: Stack(children: [
const Align(
alignment: Alignment(-0.9, 0.0),
child: Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"Power Draw")),
Align(
2023-10-19 14:26:09 +00:00
alignment: const Alignment(xOffset, 0.0),
2023-10-13 21:33:13 +00:00
child: SizedBox(
2023-10-19 14:26:09 +00:00
width: infoWidth,
2023-10-13 21:33:13 +00:00
child: Text(
textAlign: TextAlign.center, "$power_draw W")))
]))
])
]);
}
}
class PlugLed extends StatefulWidget {
PlugLed({super.key, required this.device_id, required this.led_state});
2023-10-19 14:26:09 +00:00
final String device_id;
bool led_state;
2023-10-13 21:33:13 +00:00
@override
2023-10-14 06:41:27 +00:00
State<PlugLed> createState() => PlugLedState();
2023-10-13 21:33:13 +00:00
}
class PlugLedState extends State<PlugLed> {
2023-10-14 06:41:27 +00:00
String _led_state_info = "";
2023-10-13 21:33:13 +00:00
void _toggle_led_state() {
2023-10-19 14:26:09 +00:00
String targetState;
2023-10-13 21:33:13 +00:00
2023-10-14 06:41:27 +00:00
if (widget.led_state) {
2023-10-19 14:26:09 +00:00
targetState = "off";
2023-10-13 21:33:13 +00:00
} else {
2023-10-19 14:26:09 +00:00
targetState = "on";
2023-10-13 21:33:13 +00:00
}
2023-10-19 14:26:09 +00:00
change_plug_state(widget.device_id, "led", targetState)
.then((deviceState) {
widget.led_state = deviceState["led"];
2023-10-13 21:33:13 +00:00
setState(() {
2023-10-14 06:41:27 +00:00
_led_state_info = widget.led_state ? "On" : "Off";
2023-10-13 21:33:13 +00:00
});
});
}
@override
Widget build(BuildContext context) {
2023-10-14 06:41:27 +00:00
_led_state_info = widget.led_state ? "On" : "Off";
2023-10-13 21:33:13 +00:00
return TextButton(
onPressed: _toggle_led_state,
child: Text(textAlign: TextAlign.center, _led_state_info));
}
}
class PlugPower extends StatefulWidget {
PlugPower(
{super.key,
required this.device_id,
required this.power_state,
required this.power_control});
2023-10-19 14:26:09 +00:00
final String device_id;
bool power_state;
bool power_control;
2023-10-13 21:33:13 +00:00
@override
2023-10-14 06:41:27 +00:00
State<PlugPower> createState() => PlugPowerState();
2023-10-13 21:33:13 +00:00
}
class PlugPowerState extends State<PlugPower> {
2023-10-14 06:41:27 +00:00
String _power_state_info = "";
2023-10-13 21:33:13 +00:00
void _toggle_power_state() {
2023-10-19 14:26:09 +00:00
String targetState;
2023-10-13 21:33:13 +00:00
2023-10-14 06:41:27 +00:00
if (widget.power_state) {
2023-10-19 14:26:09 +00:00
targetState = "off";
2023-10-13 21:33:13 +00:00
} else {
2023-10-19 14:26:09 +00:00
targetState = "on";
2023-10-13 21:33:13 +00:00
}
2023-10-19 14:26:09 +00:00
change_plug_state(widget.device_id, "power", targetState)
.then((deviceState) {
widget.power_state = deviceState["power"];
2023-10-13 21:33:13 +00:00
2023-10-19 14:26:09 +00:00
widget.power_control = deviceState["power_draw"] < 15;
2023-10-13 21:33:13 +00:00
setState(() {
2023-10-14 06:41:27 +00:00
_power_state_info = widget.power_state ? "On" : "Off";
2023-10-13 21:33:13 +00:00
});
});
}
@override
Widget build(BuildContext context) {
2023-10-14 06:41:27 +00:00
_power_state_info = widget.power_state ? "On" : "Off";
if (widget.power_control) {
2023-10-13 21:33:13 +00:00
return TextButton(
onPressed: _toggle_power_state,
child: Text(textAlign: TextAlign.center, _power_state_info));
} else {
return Text(_power_state_info, textAlign: TextAlign.center);
}
}
}
Future<Map<String, dynamic>> change_plug_state(
2023-10-19 14:26:09 +00:00
String deviceId, String module, String state) async {
2023-10-13 21:33:13 +00:00
var response = await http.post(
2023-10-19 14:26:09 +00:00
Uri.parse("${Constants.BASE_URL}/plug/$deviceId/${module}_$state"));
2023-10-13 21:33:13 +00:00
if (response.statusCode != 200) {
throw Exception("Failed to post new state");
}
response =
2023-10-19 14:26:09 +00:00
await http.get(Uri.parse("${Constants.BASE_URL}/plug_state/$deviceId"));
2023-10-13 21:33:13 +00:00
if (response.statusCode != 200) {
2023-10-19 14:26:09 +00:00
throw Exception("Failed to fetch plug_state for $deviceId");
2023-10-13 21:33:13 +00:00
}
return Map.castFrom(jsonDecode(jsonDecode(response.body)));
}