diff --git a/frontend/lib/constants.dart b/frontend/lib/constants.dart new file mode 100644 index 0000000..5cdd1ca --- /dev/null +++ b/frontend/lib/constants.dart @@ -0,0 +1,4 @@ +class Constants { + static const String BASE_URL = "http://127.0.0.1:8062"; +// static const String BASE_URL = "http://smart.gavania.de"; +} diff --git a/frontend/lib/devices.dart b/frontend/lib/devices.dart index 604d621..22eb5c5 100644 --- a/frontend/lib/devices.dart +++ b/frontend/lib/devices.dart @@ -4,14 +4,16 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; +import 'constants.dart'; + class Category { Category(this.name) : devices = []; final String name; List devices; - static Future> fetch(String base_url) async { - final response = await http.get(Uri.parse("http://$base_url/devices")); + static Future> fetch() async { + final response = await http.get(Uri.parse("${Constants.BASE_URL}/devices")); if (response.statusCode != 200) { throw Exception("Failed to fetch devices"); @@ -32,8 +34,8 @@ class Category { final String? device_descriptor = device_info['desc']; final bool power_control = device_info['toggle']; - final response = - await http.get(Uri.parse("http://$base_url/plug_state/$device_id")); + final response = await http + .get(Uri.parse("${Constants.BASE_URL}/plug_state/$device_id")); if (response.statusCode != 200) { throw Exception("Failed to fetch plug_state for $device_id"); @@ -77,18 +79,12 @@ class CategoryWidget extends StatelessWidget { Text( textAlign: TextAlign.center, device.device_descriptor ?? device.device_id), - TextButton( - child: Text( - textAlign: TextAlign.center, - device.led_state ? 'On' : 'Off'), - onPressed: () {}, - ), - TextButton( - child: Text( - textAlign: TextAlign.center, - device.power_state ? 'On' : 'Off'), - onPressed: () {}, - ), + DeviceLed( + device_id: device.device_id, led_state: device.led_state), + DevicePower( + device_id: device.device_id, + power_state: device.power_state, + power_control: device.power_control), Text(textAlign: TextAlign.center, "${device.power_draw} W") ])) .toList(); @@ -142,3 +138,123 @@ class Device { Device(this.device_id, this.device_descriptor, this.led_state, this.power_state, this.power_draw, this.power_control); } + +class DeviceLed extends StatefulWidget { + final String device_id; + final bool led_state; + + DeviceLed({super.key, required this.device_id, required this.led_state}); + + @override + State createState() => DeviceLedState(device_id, led_state); +} + +class DeviceLedState extends State { + final String device_id; + bool led_state; + String _led_state_info; + + DeviceLedState(this.device_id, this.led_state) + : this._led_state_info = led_state ? "On" : "Off"; + + void _toggle_led_state() { + String target_state; + + if (led_state) { + target_state = "off"; + } else { + target_state = "on"; + } + + change_plug_state(device_id, "led", target_state).then((device_state) { + led_state = device_state["led"]; + + setState(() { + _led_state_info = led_state ? "On" : "Off"; + }); + }); + } + + @override + Widget build(BuildContext context) { + return TextButton( + onPressed: _toggle_led_state, + child: Text(textAlign: TextAlign.center, _led_state_info)); + } +} + +class DevicePower extends StatefulWidget { + final String device_id; + final bool power_state; + final bool power_control; + + DevicePower( + {super.key, + required this.device_id, + required this.power_state, + required this.power_control}); + + @override + State createState() => + DevicePowerState(device_id, power_state, power_control); +} + +class DevicePowerState extends State { + final String device_id; + bool power_state; + String _power_state_info; + bool power_control; + + DevicePowerState(this.device_id, this.power_state, this.power_control) + : this._power_state_info = power_state ? "On" : "Off"; + + void _toggle_power_state() { + String target_state; + + if (power_state) { + target_state = "off"; + } else { + target_state = "on"; + } + + change_plug_state(device_id, "power", target_state).then((device_state) { + power_state = device_state["power"]; + + power_control = device_state["power_draw"] < 15; + + setState(() { + _power_state_info = power_state ? "On" : "Off"; + }); + }); + } + + @override + Widget build(BuildContext context) { + if (power_control) { + return TextButton( + onPressed: _toggle_power_state, + child: Text(textAlign: TextAlign.center, _power_state_info)); + } else { + return Text(_power_state_info, textAlign: TextAlign.center); + } + } +} + +Future> change_plug_state( + String device_id, String module, String state) async { + var response = await http.post( + Uri.parse("${Constants.BASE_URL}/plug/$device_id/${module}_$state")); + + if (response.statusCode != 200) { + throw Exception("Failed to post new state"); + } + + response = + await http.get(Uri.parse("${Constants.BASE_URL}/plug_state/$device_id")); + + if (response.statusCode != 200) { + throw Exception("Failed to fetch plug_state for $device_id"); + } + + return Map.castFrom(jsonDecode(jsonDecode(response.body))); +} diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 97b332b..8af3c60 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -36,8 +36,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { return FutureBuilder>( - // future: Category.fetch("smart.gavania.de"), - future: Category.fetch("127.0.0.1:8062"), + future: Category.fetch(), builder: (context, AsyncSnapshot> categories) { if (!categories.hasData) { return const Text("still loading");