Get a table to be displayed

This commit is contained in:
hodasemi 2023-10-10 14:06:26 +02:00
parent adc19c845c
commit ab477c08a9
4 changed files with 119 additions and 116 deletions

View file

@ -11,8 +11,6 @@ class Category {
List<Device> devices;
static Future<List<Category>> fetch(String base_url) async {
print("fetch: http://$base_url/devices");
final response = await http.get(Uri.parse("http://$base_url/devices"));
if (response.statusCode != 200) {
@ -21,54 +19,43 @@ class Category {
final List<Category> categories = [];
print(response.body);
print("body type: ${response.body.runtimeType}");
final Map<String, List<dynamic>> json =
Map.castFrom(jsonDecode(jsonDecode(response.body)));
final json = jsonDecode(response.body);
for (MapEntry<String, List<dynamic>> category_entry in json.entries) {
final Category category = Category(category_entry.key);
print(json);
print("json type: ${json.runtimeType}");
for (dynamic device_info_dyn in category_entry.value) {
final Map<String, dynamic> device_info = device_info_dyn;
final Map<String, List<List<dynamic>>> test = jsonDecode(json);
final String device_id = device_info['id'];
final String? device_descriptor = device_info['desc'];
final bool power_control = device_info['toggle'];
print(test);
print("test type: ${test.runtimeType}");
final response =
await http.get(Uri.parse("http://$base_url/plug_state/$device_id"));
// final Map<String, List<List<dynamic>>> json = jsonDecode(response.body);
if (response.statusCode != 200) {
throw Exception("Failed to fetch plug_state for $device_id");
}
// for (MapEntry<String, List<List<dynamic>>> category_entry in json.entries) {
// final Category category = Category(category_entry.key);
final Map<String, dynamic> device_state =
Map.castFrom(jsonDecode(jsonDecode(response.body)));
// for (List<dynamic> device_info in category_entry.value) {
// final String device_id = device_info[0];
// final String? device_descriptor = device_info[1];
// final bool power_control = device_info[2];
final Device device = Device(
device_id,
device_descriptor,
device_state["led"],
device_state["power"],
device_state["power_draw"],
power_control && device_state["power_draw"] < 15,
);
// final response =
// await http.get(Uri.parse("$base_url/plug_state/$device_id"));
category.devices.add(device);
}
// if (response.statusCode != 200) {
// throw Exception("Failed to fetch plug_state for $device_id");
// }
// print(response.body);
// final Map<String, dynamic> device_state = jsonDecode(response.body);
// final Device device = Device(
// device_id,
// device_descriptor,
// device_state["led"],
// device_state["power"],
// device_state["power_draw"],
// power_control && device_state["power_draw"] < 15,
// );
// category.devices.add(device);
// }
// categories.add(category);
// }
categories.add(category);
}
return categories;
}
@ -79,28 +66,68 @@ class CategoryWidget extends StatelessWidget {
CategoryWidget({super.key, required this.category});
String capitalize(String s) {
return "${s[0].toUpperCase()}${s.substring(1)}";
}
@override
Widget build(BuildContext context) {
var list = category.devices
.map((device) => TableRow(children: [
Text(device.device_descriptor ?? device.device_id),
Text(device.led_state.toString()),
Text(device.power_state.toString()),
Text("${device.power_draw} W")
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: () {},
),
Text(textAlign: TextAlign.center, "${device.power_draw} W")
]))
.toList();
list.insert(
0,
const TableRow(children: [
Text("Name"),
Text("LED"),
Text("Power"),
Text("Power Draw"),
]));
const TableRow(
decoration: BoxDecoration(
color: Colors.blueGrey,
),
children: [
Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"Name"),
Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"LED"),
Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"Power"),
Text(
style: TextStyle(fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
"Power Draw"),
]));
return Column(
children: <Widget>[Text(category.name), Table(children: list)]);
return Column(children: <Widget>[
Text(
style: const TextStyle(fontWeight: FontWeight.bold),
textScaleFactor: 2.0,
capitalize(category.name)),
Table(
border: TableBorder.all(),
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
children: list)
]);
}
}

View file

@ -13,27 +13,12 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
title: 'SmartHome',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a blue toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
home: const MyHomePage(title: 'SmartHome Main Page'),
);
}
}
@ -41,15 +26,6 @@ class MyApp extends StatelessWidget {
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
@ -59,38 +35,27 @@ class MyHomePage extends StatefulWidget {
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
final Future<List<Category>> fut = Category.fetch("127.0.0.1:8062");
// final Future<List<Category>> fut = Category.fetch("smart.gavania.de");
return FutureBuilder<List<Category>>(
// future: Category.fetch("smart.gavania.de"),
future: Category.fetch("127.0.0.1:8062"),
builder: (context, AsyncSnapshot<List<Category>> categories) {
if (!categories.hasData) {
return const Text("still loading");
}
List<Widget> children = List.empty();
fut.then((categories) {
children = categories
.map((category) => CategoryWidget(category: category))
.toList();
});
// return FutureBuilder<List<Category>>(
// future: Category.fetch("smart.gavania.de"),
// builder: (context, AsyncSnapshot<List<Category>> categories) {
// if (!categories.hasData) {
// return const Text("still loading");
// }
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// children: categories.data!
// .map((category) => CategoryWidget(category: category))
// .toList(),
children: children,
),
));
// });
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: categories.data!
.map((category) => CategoryWidget(category: category))
.toList(),
),
));
});
}
}

View file

@ -3,7 +3,7 @@ use std::path::Path;
use anyhow::Result;
use rusqlite::{Connection, OptionalExtension, ToSql};
use crate::devices::{Devices, DevicesWithName};
use crate::devices::{DeviceWithName, Devices, DevicesWithName};
pub struct DataBase {
sql: Connection,
@ -151,7 +151,11 @@ impl DataBase {
let (device, dev_type, name, control): (String, String, Option<String>, i32) = row?;
match dev_type.as_str() {
"plug" => devices.plugs.push((device, name, control != 0)),
"plug" => devices.plugs.push(DeviceWithName {
id: device,
desc: name,
toggle: control != 0,
}),
_ => panic!(),
}
@ -313,8 +317,8 @@ mod test {
let devices = db.devices()?;
assert_eq!(devices.plugs[0].1.as_ref().unwrap(), device_descriptor);
assert_eq!(devices.plugs[0].0, device_name);
assert_eq!(devices.plugs[0].desc.as_ref().unwrap(), device_descriptor);
assert_eq!(devices.plugs[0].id, device_name);
fs::remove_file("write_test.db")?;

View file

@ -24,9 +24,16 @@ impl Devices {
}
}
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct DeviceWithName {
pub id: String,
pub desc: Option<String>,
pub toggle: bool,
}
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct DevicesWithName {
pub plugs: Vec<(String, Option<String>, bool)>,
pub plugs: Vec<DeviceWithName>,
}
impl DevicesWithName {