Get a table to be displayed
This commit is contained in:
parent
adc19c845c
commit
ab477c08a9
4 changed files with 119 additions and 116 deletions
|
@ -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)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/db.rs
12
src/db.rs
|
@ -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")?;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue