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; List<Device> devices;
static Future<List<Category>> fetch(String base_url) async { 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")); final response = await http.get(Uri.parse("http://$base_url/devices"));
if (response.statusCode != 200) { if (response.statusCode != 200) {
@ -21,54 +19,43 @@ class Category {
final List<Category> categories = []; final List<Category> categories = [];
print(response.body); final Map<String, List<dynamic>> json =
print("body type: ${response.body.runtimeType}"); 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); for (dynamic device_info_dyn in category_entry.value) {
print("json type: ${json.runtimeType}"); 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); final response =
print("test type: ${test.runtimeType}"); 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 Map<String, dynamic> device_state =
// final Category category = Category(category_entry.key); Map.castFrom(jsonDecode(jsonDecode(response.body)));
// for (List<dynamic> device_info in category_entry.value) { final Device device = Device(
// final String device_id = device_info[0]; device_id,
// final String? device_descriptor = device_info[1]; device_descriptor,
// final bool power_control = device_info[2]; device_state["led"],
device_state["power"],
device_state["power_draw"],
power_control && device_state["power_draw"] < 15,
);
// final response = category.devices.add(device);
// await http.get(Uri.parse("$base_url/plug_state/$device_id")); }
// if (response.statusCode != 200) { categories.add(category);
// 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);
// }
return categories; return categories;
} }
@ -79,28 +66,68 @@ class CategoryWidget extends StatelessWidget {
CategoryWidget({super.key, required this.category}); CategoryWidget({super.key, required this.category});
String capitalize(String s) {
return "${s[0].toUpperCase()}${s.substring(1)}";
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var list = category.devices var list = category.devices
.map((device) => TableRow(children: [ .map((device) => TableRow(children: [
Text(device.device_descriptor ?? device.device_id), Text(
Text(device.led_state.toString()), textAlign: TextAlign.center,
Text(device.power_state.toString()), device.device_descriptor ?? device.device_id),
Text("${device.power_draw} W") 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(); .toList();
list.insert( list.insert(
0, 0,
const TableRow(children: [ const TableRow(
Text("Name"), decoration: BoxDecoration(
Text("LED"), color: Colors.blueGrey,
Text("Power"), ),
Text("Power Draw"), 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( return Column(children: <Widget>[
children: <Widget>[Text(category.name), Table(children: list)]); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: 'Flutter Demo', title: 'SmartHome',
theme: ThemeData( 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), colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true, 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 { class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title}); 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; final String title;
@override @override
@ -59,38 +35,27 @@ class MyHomePage extends StatefulWidget {
class _MyHomePageState extends State<MyHomePage> { class _MyHomePageState extends State<MyHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Future<List<Category>> fut = Category.fetch("127.0.0.1:8062"); return FutureBuilder<List<Category>>(
// final Future<List<Category>> fut = Category.fetch("smart.gavania.de"); // 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(); return Scaffold(
appBar: AppBar(
fut.then((categories) { backgroundColor: Theme.of(context).colorScheme.inversePrimary,
children = categories title: Text(widget.title),
.map((category) => CategoryWidget(category: category)) ),
.toList(); body: Center(
}); child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// return FutureBuilder<List<Category>>( children: categories.data!
// future: Category.fetch("smart.gavania.de"), .map((category) => CategoryWidget(category: category))
// builder: (context, AsyncSnapshot<List<Category>> categories) { .toList(),
// 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,
),
));
// });
} }
} }

View file

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