2023-10-05 08:09:25 +00:00
|
|
|
function group_name({ name }) {
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td>{name}</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function table_header() {
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td>Name</td>
|
|
|
|
<td>LED</td>
|
|
|
|
<td>Power</td>
|
|
|
|
<td>Power Draw</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function table_row({ row_data }) {
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
{/* Name */}
|
|
|
|
<td>
|
|
|
|
<input id={"name_" + row_data.device_id} readonly="true">{row_data.device_name}</input>
|
|
|
|
<button on_click={async () => { await change_name(row_data.device_id) }}>
|
|
|
|
<i class="fa fa-pencil-square-o"></i>
|
|
|
|
</button>
|
|
|
|
</td>
|
|
|
|
|
|
|
|
{/* LED */}
|
|
|
|
<td>
|
|
|
|
<label id={"led_" + row_data.device_id}>{row_data.led_state}</label>
|
|
|
|
<button on_click={async () => { await led_on(row_data.device_id) }}>On</button>
|
|
|
|
<button on_click={async () => { await led_off(row_data.device_id) }}>Off</button>
|
|
|
|
</td>
|
|
|
|
|
|
|
|
{/* Power */}
|
|
|
|
<td>
|
|
|
|
<label id={"power_" + row_data.device_id}>{row_data.power_state}</label>
|
|
|
|
{
|
|
|
|
row_data.power_control &&
|
|
|
|
<button on_click={async () => { await power_on(row_data.device_id) }}>On</button> &&
|
|
|
|
<button on_click={async () => { await power_off(row_data.device_id) }}>Off</button>
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
{/* Power Draw */}
|
|
|
|
<td>
|
|
|
|
<label>{row_data.power_draw} W</label>
|
|
|
|
<button><i class="fa fa-line-chart"></i></button>
|
|
|
|
</td>
|
|
|
|
</tr >
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function create_table(group, device_data) {
|
|
|
|
return (
|
|
|
|
<table>
|
|
|
|
<group_name name={group} />
|
|
|
|
<table_header />
|
|
|
|
<table_row row_data={device_data} />
|
|
|
|
</table>
|
|
|
|
);
|
|
|
|
}
|
2023-09-21 08:46:23 +00:00
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
export default async function MyApp() {
|
2023-09-21 09:22:03 +00:00
|
|
|
const response = await fetch(
|
|
|
|
"/devices",
|
|
|
|
{
|
|
|
|
method: "GET"
|
|
|
|
}
|
|
|
|
);
|
2023-09-21 08:46:23 +00:00
|
|
|
|
2023-09-21 11:32:44 +00:00
|
|
|
let json = JSON.parse(await response.json());
|
2023-09-21 09:22:03 +00:00
|
|
|
|
2023-09-21 11:32:44 +00:00
|
|
|
for (const [group_name, devices] of Object.entries(json)) {
|
2023-10-05 08:09:25 +00:00
|
|
|
let device_infos = [];
|
2023-09-21 11:32:44 +00:00
|
|
|
|
|
|
|
for (let i = 0; i < devices.length; i++) {
|
|
|
|
let device_id = devices[i][0];
|
2023-09-21 11:56:03 +00:00
|
|
|
let device_descriptor;
|
|
|
|
|
|
|
|
if (devices[i][1] == null) {
|
|
|
|
device_descriptor = device_id
|
|
|
|
} else {
|
|
|
|
device_descriptor = devices[i][1];
|
|
|
|
}
|
2023-09-21 11:32:44 +00:00
|
|
|
|
2023-09-21 20:20:42 +00:00
|
|
|
// get plug status
|
2023-09-21 11:32:44 +00:00
|
|
|
const device_status_response = await fetch(
|
|
|
|
"/plug_state/" + device_id,
|
|
|
|
{
|
|
|
|
method: "GET"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
let device_state = JSON.parse(await device_status_response.json());
|
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
let device_info = {
|
|
|
|
device_id: device_id,
|
|
|
|
device_descriptor: device_descriptor,
|
|
|
|
led_state: device_state["led"],
|
|
|
|
power_state: device_state["power"],
|
|
|
|
power_control: devices[i][2] && device_state["power_draw"] < 15,
|
|
|
|
power_draw: device_state["power_draw"],
|
|
|
|
};
|
2023-09-22 05:43:56 +00:00
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
device_infos.push(device_info);
|
|
|
|
}
|
2023-09-21 11:32:44 +00:00
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
document.getElementById("main").appendChild(create_table(group_name, device_infos));
|
|
|
|
}
|
|
|
|
}
|
2023-09-21 20:20:42 +00:00
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
async function change_name(device_id) {
|
|
|
|
let device_name = document.getElementById("name_" + device_id);
|
2023-09-21 11:32:44 +00:00
|
|
|
|
2023-10-05 08:09:25 +00:00
|
|
|
if (device_name.readOnly) {
|
|
|
|
device_name.readOnly = false;
|
|
|
|
device_name.focus();
|
|
|
|
} else {
|
|
|
|
device_name.readOnly = true;
|
|
|
|
await change_device_name(device_id, device_name.value);
|
2023-09-21 11:32:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-21 11:56:03 +00:00
|
|
|
async function change_plug_state(plug, module, state) {
|
2023-09-21 11:32:44 +00:00
|
|
|
const response = await fetch(
|
2023-09-21 11:56:03 +00:00
|
|
|
"/plug/" + plug + "/" + module + "_" + state,
|
2023-09-21 11:32:44 +00:00
|
|
|
{
|
|
|
|
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());
|
|
|
|
|
2023-09-21 11:56:03 +00:00
|
|
|
document.getElementById(module + "_" + plug).innerHTML = device_state[module];
|
2023-09-21 11:32:44 +00:00
|
|
|
}
|
2023-09-21 11:56:03 +00:00
|
|
|
}
|
2023-09-21 11:32:44 +00:00
|
|
|
|
2023-09-21 11:56:03 +00:00
|
|
|
async function led_on(plug) {
|
|
|
|
await change_plug_state(plug, "led", "on")
|
2023-09-21 11:32:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function led_off(plug) {
|
2023-09-21 11:56:03 +00:00
|
|
|
await change_plug_state(plug, "led", "off")
|
2023-09-21 11:32:44 +00:00
|
|
|
}
|
2023-09-21 09:22:03 +00:00
|
|
|
|
2023-09-21 11:32:44 +00:00
|
|
|
async function power_on(plug) {
|
2023-09-21 11:56:03 +00:00
|
|
|
await change_plug_state(plug, "power", "on")
|
2023-09-21 09:22:03 +00:00
|
|
|
}
|
|
|
|
|
2023-09-21 11:32:44 +00:00
|
|
|
async function power_off(plug) {
|
2023-09-25 11:04:02 +00:00
|
|
|
// get plug status
|
|
|
|
const device_status_response = await fetch(
|
|
|
|
"/plug_state/" + device_id,
|
|
|
|
{
|
|
|
|
method: "GET"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
let device_state = JSON.parse(await device_status_response.json());
|
|
|
|
|
|
|
|
if (device_state["power_draw"] < 15) {
|
|
|
|
await change_plug_state(plug, "power", "off")
|
|
|
|
}
|
2023-09-21 11:56:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function change_device_name(plug, name) {
|
2023-09-21 11:32:44 +00:00
|
|
|
const response = await fetch(
|
2023-09-21 11:56:03 +00:00
|
|
|
"/device_name/" + plug + "/" + name,
|
2023-09-21 11:32:44 +00:00
|
|
|
{
|
|
|
|
method: "POST"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-09-21 11:56:03 +00:00
|
|
|
if (!response.ok) {
|
|
|
|
console.error(response.body);
|
2023-09-21 11:32:44 +00:00
|
|
|
}
|
2023-09-21 20:20:42 +00:00
|
|
|
}
|
|
|
|
|
2023-09-22 04:21:58 +00:00
|
|
|
async function render_graph(plug, name) {
|
2023-09-21 20:20:42 +00:00
|
|
|
// remove old graph, if present
|
|
|
|
let old = document.getElementById("chart");
|
|
|
|
|
|
|
|
if (old !== null) {
|
|
|
|
old.remove();
|
|
|
|
}
|
|
|
|
|
2023-10-02 08:41:24 +00:00
|
|
|
// get start date
|
|
|
|
let start_text = document.getElementById("start").value;
|
|
|
|
let start_date = parseInt(new Date(start_text).getTime() / 1000).toFixed(0);
|
|
|
|
|
|
|
|
// get end date1
|
|
|
|
let end_text = document.getElementById("end").value;
|
|
|
|
let end_date = parseInt(new Date(end_text).getTime() / 1000).toFixed(0);
|
|
|
|
|
2023-09-21 20:20:42 +00:00
|
|
|
// create new chart div
|
|
|
|
let chart = document.createElement('canvas');
|
|
|
|
chart.id = "chart";
|
|
|
|
|
|
|
|
const response = await fetch(
|
2023-10-02 08:41:24 +00:00
|
|
|
"/plug_data/" + plug + "/" + start_date + "/" + end_date + "/" + "hourly",
|
2023-09-21 20:20:42 +00:00
|
|
|
{
|
|
|
|
method: "GET"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const j = await response.json();
|
|
|
|
const data = JSON.parse(j);
|
|
|
|
|
|
|
|
let y = [];
|
|
|
|
let x = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
let [time, watts] = data[i];
|
|
|
|
|
2023-09-22 04:21:58 +00:00
|
|
|
x.push(new Date(time * 1000));
|
2023-09-21 20:20:42 +00:00
|
|
|
y.push(watts);
|
|
|
|
}
|
|
|
|
|
|
|
|
const chart_data = {
|
|
|
|
labels: x,
|
|
|
|
datasets: [{
|
2023-09-22 04:21:58 +00:00
|
|
|
label: name,
|
2023-09-21 20:20:42 +00:00
|
|
|
data: y,
|
|
|
|
fill: false,
|
|
|
|
borderColor: 'rgb(75, 192, 192)',
|
|
|
|
tension: 0.1
|
|
|
|
}]
|
|
|
|
};
|
|
|
|
|
|
|
|
new Chart(chart, {
|
|
|
|
type: 'line',
|
|
|
|
data: chart_data,
|
2023-09-22 04:21:58 +00:00
|
|
|
options: {
|
|
|
|
scales: {
|
|
|
|
y: {
|
|
|
|
beginAtZero: true
|
|
|
|
},
|
|
|
|
x: {
|
|
|
|
type: 'time',
|
|
|
|
time: {
|
|
|
|
displayFormats: {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
locale: 'de-DE'
|
|
|
|
}
|
2023-09-21 20:20:42 +00:00
|
|
|
});
|
|
|
|
|
2023-10-02 08:41:24 +00:00
|
|
|
document.getElementById("graph").appendChild(chart);
|
2023-09-21 11:56:03 +00:00
|
|
|
}
|