Implement basic web view

This commit is contained in:
hodasemi 2023-09-21 13:32:44 +02:00
parent 2be07df8da
commit ace45e2efe
3 changed files with 246 additions and 26 deletions

View file

@ -0,0 +1,5 @@
table,
th,
td {
border: 1px solid black;
}

View file

@ -8,35 +8,191 @@ async function startup() {
} }
); );
const div = document.getElementById("main"); let table = document.createElement('table');
let json = JSON.parse(await response.json());
let json = await response.json();
console.log(json); console.log(json);
console.log(json["plugs"]); for (const [group_name, devices] of Object.entries(json)) {
let row_group = document.createElement('tr');
let data_group = document.createElement('td');
let group_label = document.createElement('label');
group_label.innerText = group_name;
Object.keys(json).forEach(entry => { data_group.appendChild(group_label);
console.log(entry); row_group.appendChild(data_group);
table.appendChild(row_group);
// const [group_name, devices] = entry; let row_header = document.createElement('tr');
let header_name_entry = document.createElement('td');
header_name_entry.innerText = "Name"
let header_led_entry = document.createElement('td');
header_led_entry.innerText = "LED"
let header_power_entry = document.createElement('td');
header_power_entry.innerText = "Power"
let header_power_draw_entry = document.createElement('td');
header_power_draw_entry.innerText = "Power Draw";
// let group_label = document.createElement('label'); row_header.appendChild(header_name_entry);
// group_label.innerText = group_name; row_header.appendChild(header_led_entry);
row_header.appendChild(header_power_entry);
row_header.appendChild(header_power_draw_entry);
table.appendChild(row_header);
// div.appendChild(group_label); for (let i = 0; i < devices.length; i++) {
let device_id = devices[i][0];
// for (let i = 0; i < devices.length; i++) { let row_device = document.createElement('tr');
// let device_div = document.createElement('div');
// let dev_name = document.createElement('label'); let device_name_entry = document.createElement('td');
// dev_name.innerText = devices[i][0]; let device_name = document.createElement('label');
device_name.innerText = device_id;
// device_div.appendChild(dev_name); device_name_entry.appendChild(device_name);
// div.appendChild(device_div); row_device.appendChild(device_name_entry);
// }
}) const device_status_response = await fetch(
"/plug_state/" + device_id,
{
method: "GET"
}
);
let device_state = JSON.parse(await device_status_response.json());
let device_led_state_entry = document.createElement('td');
let device_led_state = document.createElement('label');
device_led_state.innerText = device_state["led"];
device_led_state.id = "led_" + device_id;
let device_led_on = document.createElement('button');
device_led_on.innerText = "On"
device_led_on.onclick = async () => { await led_on(device_id) };
let device_led_off = document.createElement('button');
device_led_off.innerText = "Off"
device_led_off.onclick = async () => { await led_off(device_id) };
device_led_state_entry.appendChild(device_led_state);
device_led_state_entry.appendChild(device_led_on);
device_led_state_entry.appendChild(device_led_off);
row_device.appendChild(device_led_state_entry);
let device_power_state_entry = document.createElement('td');
let device_power_state = document.createElement('label');
device_power_state.innerText = device_state["power"];
device_power_state.id = "power_" + device_id;
let device_power_on = document.createElement('button');
device_power_on.innerText = "On"
device_power_on.onclick = async () => { await power_on(device_id) };
let device_power_off = document.createElement('button');
device_power_off.innerText = "Off"
device_power_off.onclick = async () => { await power_off(device_id) };
device_power_state_entry.appendChild(device_power_state);
device_power_state_entry.appendChild(device_power_on);
device_power_state_entry.appendChild(device_power_off);
row_device.appendChild(device_power_state_entry);
let device_power_draw_entry = document.createElement('td');
let device_power_draw_ = document.createElement('label');
device_power_draw_.innerText = device_state["power_draw"] + " W";
device_power_draw_entry.appendChild(device_power_draw_);
row_device.appendChild(device_power_draw_entry);
table.appendChild(row_device);
}
}
document.getElementById("main").appendChild(table);
}
async function led_on(plug) {
const response = await fetch(
"/plug/" + plug + "/led_on",
{
method: "POST"
}
);
if (response.ok) {
const device_status_response = await fetch(
"/plug_state/" + plug,
{
method: "GET"
}
);
let device_state = JSON.parse(await device_status_response.json());
document.getElementById("led_" + plug).innerHTML = device_state["led"];
} }
}
async function led_off(plug) {
const response = await fetch(
"/plug/" + plug + "/led_off",
{
method: "POST"
}
);
if (response.ok) {
const device_status_response = await fetch(
"/plug_state/" + plug,
{
method: "GET"
}
);
let device_state = JSON.parse(await device_status_response.json());
document.getElementById("led_" + plug).innerHTML = device_state["led"];
}
}
async function power_on(plug) {
const response = await fetch(
"/plug/" + plug + "/power_on",
{
method: "POST"
}
);
if (response.ok) {
const device_status_response = await fetch(
"/plug_state/" + plug,
{
method: "GET"
}
);
let device_state = JSON.parse(await device_status_response.json());
document.getElementById("power_" + plug).innerHTML = device_state["power"];
}
}
async function power_off(plug) {
const response = await fetch(
"/plug/" + plug + "/power_off",
{
method: "POST"
}
);
if (response.ok) {
const device_status_response = await fetch(
"/plug_state/" + plug,
{
method: "GET"
}
);
let device_state = JSON.parse(await device_status_response.json());
document.getElementById("power_" + plug).innerHTML = device_state["power"];
}
}

View file

@ -69,13 +69,14 @@ async fn device_query(
#[post("/device_name/{device}/{name}")] #[post("/device_name/{device}/{name}")]
async fn change_device_name( async fn change_device_name(
device: Path<String>, param: Path<(String, String)>,
name: Path<String>,
db: Data<Arc<Mutex<DataBase>>>, db: Data<Arc<Mutex<DataBase>>>,
) -> Result<impl Responder, MyError> { ) -> Result<impl Responder, MyError> {
let (device, name) = param.into_inner();
db.lock() db.lock()
.unwrap() .unwrap()
.change_device_name(&device.into_inner(), &name.into_inner()) .change_device_name(&device, &name)
.map_err(|err| MyError::from(err))?; .map_err(|err| MyError::from(err))?;
return Ok("Ok"); return Ok("Ok");
@ -115,14 +116,13 @@ async fn plug_state(
#[post("/plug/{plug}/{action}")] #[post("/plug/{plug}/{action}")]
async fn change_plug_state( async fn change_plug_state(
plug: Path<String>, param: Path<(String, String)>,
action: Path<String>,
plugs: Data<Vec<Tasmota>>, plugs: Data<Vec<Tasmota>>,
) -> Result<impl Responder, impl ResponseError> { ) -> Result<impl Responder, impl ResponseError> {
let plug_name = plug.into_inner(); let (plug_name, action_type) = param.into_inner();
if let Some(tasmota) = plugs.iter().find(|tasmota| tasmota.name() == plug_name) { if let Some(tasmota) = plugs.iter().find(|tasmota| tasmota.name() == plug_name) {
match action.into_inner().as_str() { match action_type.as_str() {
"led_on" => tasmota "led_on" => tasmota
.turn_on_led() .turn_on_led()
.await .await
@ -154,6 +154,8 @@ async fn change_plug_state(
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use actix_web::{http::header::ContentType, test, App}; use actix_web::{http::header::ContentType, test, App};
use reqwest::Method;
use std::{thread, time::Duration};
use super::*; use super::*;
@ -168,6 +170,63 @@ mod test {
let status = resp.status(); let status = resp.status();
let body = resp.into_body(); let body = resp.into_body();
assert!(status.is_success(), "{:?}", body); assert!(
status.is_success(),
"status: {:?}, error: {:?}",
status,
body
);
}
#[actix_web::test]
async fn test_led_on_off() {
let app = test::init_service(
App::new()
.service(change_plug_state)
.app_data(Data::new(vec![Tasmota::new("Tasmota-Plug-3")])),
)
.await;
{
let req = test::TestRequest::default()
.uri("/plug/Tasmota-Plug-3/led_off")
.insert_header(ContentType::plaintext())
.method(Method::POST)
.to_request();
let resp = test::call_service(&app, req).await;
let status = resp.status();
let body = resp.into_body();
assert!(
status.is_success(),
"status: {:?}, error: {:?}",
status,
body
);
}
thread::sleep(Duration::from_secs(5));
{
let req = test::TestRequest::default()
.uri("/plug/Tasmota-Plug-3/led_on")
.insert_header(ContentType::plaintext())
.method(Method::POST)
.to_request();
let resp = test::call_service(&app, req).await;
let status = resp.status();
let body = resp.into_body();
assert!(
status.is_success(),
"status: {:?}, error: {:?}",
status,
body
);
}
} }
} }