This commit is contained in:
proddy
2021-05-14 12:45:57 +02:00
parent 15df0c0552
commit fec5ff3132
108 changed files with 3508 additions and 2455 deletions

View File

@@ -1,38 +1,62 @@
import React, { Component, Fragment } from "react";
import { withStyles, Theme, createStyles } from "@material-ui/core/styles";
import React, { Component, Fragment } from 'react';
import { withStyles, Theme, createStyles } from '@material-ui/core/styles';
import {
Table, TableBody, TableCell, TableHead, TableRow, TableContainer, withWidth, WithWidthProps, isWidthDown,
Button, Tooltip, DialogTitle, DialogContent, DialogActions, Box, Dialog, Typography
} from "@material-ui/core";
Table,
TableBody,
TableCell,
TableHead,
TableRow,
TableContainer,
withWidth,
WithWidthProps,
isWidthDown,
Button,
Tooltip,
DialogTitle,
DialogContent,
DialogActions,
Box,
Dialog,
Typography
} from '@material-ui/core';
import RefreshIcon from "@material-ui/icons/Refresh";
import ListIcon from "@material-ui/icons/List";
import RefreshIcon from '@material-ui/icons/Refresh';
import ListIcon from '@material-ui/icons/List';
import IconButton from '@material-ui/core/IconButton';
import EditIcon from '@material-ui/icons/Edit';
import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from "../authentication";
import { RestFormProps, FormButton, extractEventValue } from "../components";
import {
redirectingAuthorizedFetch,
withAuthenticatedContext,
AuthenticatedContextProps
} from '../authentication';
import { RestFormProps, FormButton, extractEventValue } from '../components';
import { EMSESPDevices, EMSESPDeviceData, Device, DeviceValue } from "./EMSESPtypes";
import {
EMSESPDevices,
EMSESPDeviceData,
Device,
DeviceValue
} from './EMSESPtypes';
import ValueForm from './ValueForm';
import { ENDPOINT_ROOT } from "../api";
import { ENDPOINT_ROOT } from '../api';
export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices";
export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + "deviceData";
export const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + "writeValue";
export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + 'scanDevices';
export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + 'deviceData';
export const WRITE_VALUE_ENDPOINT = ENDPOINT_ROOT + 'writeValue';
const StyledTableCell = withStyles((theme: Theme) =>
createStyles({
head: {
backgroundColor: theme.palette.common.black,
color: theme.palette.common.white,
color: theme.palette.common.white
},
body: {
fontSize: 14,
},
fontSize: 14
}
})
)(TableCell);
@@ -42,8 +66,8 @@ const CustomTooltip = withStyles((theme: Theme) => ({
color: 'white',
boxShadow: theme.shadows[1],
fontSize: 11,
border: '1px solid #dadde9',
},
border: '1px solid #dadde9'
}
}))(Tooltip);
function compareDevices(a: Device, b: Device) {
@@ -64,63 +88,81 @@ interface EMSESPDevicesFormState {
devicevalue?: DeviceValue;
}
type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> & AuthenticatedContextProps & WithWidthProps;
type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> &
AuthenticatedContextProps &
WithWidthProps;
function formatTemp(t: string) {
if (t == null) {
return "n/a";
return 'n/a';
}
return t + " °C";
return t + ' °C';
}
function formatUnit(u: string) {
if (u == null) {
return u;
}
return " " + u;
return ' ' + u;
}
class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesFormState> {
class EMSESPDevicesForm extends Component<
EMSESPDevicesFormProps,
EMSESPDevicesFormState
> {
state: EMSESPDevicesFormState = {
confirmScanDevices: false,
processing: false
};
handleValueChange = (name: keyof DeviceValue) => (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ devicevalue: { ...this.state.devicevalue!, [name]: extractEventValue(event) } });
handleValueChange = (name: keyof DeviceValue) => (
event: React.ChangeEvent<HTMLInputElement>
) => {
this.setState({
devicevalue: {
...this.state.devicevalue!,
[name]: extractEventValue(event)
}
});
};
cancelEditingValue = () => {
this.setState({
devicevalue: undefined
});
}
};
doneEditingValue = () => {
const { devicevalue } = this.state;
redirectingAuthorizedFetch(WRITE_VALUE_ENDPOINT, {
method: "POST",
method: 'POST',
body: JSON.stringify({ devicevalue: devicevalue }),
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
})
.then((response) => {
if (response.status === 200) {
this.props.enqueueSnackbar("Write command sent to device", { variant: "success" });
this.props.enqueueSnackbar('Write command sent to device', {
variant: 'success'
});
} else if (response.status === 204) {
this.props.enqueueSnackbar("Write command failed", { variant: "error" });
this.props.enqueueSnackbar('Write command failed', {
variant: 'error'
});
} else if (response.status === 403) {
this.props.enqueueSnackbar("Write access denied", { variant: "error" });
this.props.enqueueSnackbar('Write access denied', {
variant: 'error'
});
} else {
throw Error("Unexpected response code: " + response.status);
throw Error('Unexpected response code: ' + response.status);
}
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || "Problem writing value", { variant: "error" }
);
this.props.enqueueSnackbar(error.message || 'Problem writing value', {
variant: 'error'
});
});
if (devicevalue) {
@@ -128,20 +170,19 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
devicevalue: undefined
});
}
};
sendCommand = (i: any) => {
sendCommand = (i: number) => {
this.setState({
devicevalue: {
id: this.state.selectedDevice!,
data: this.state.deviceData?.data[i]!,
uom: this.state.deviceData?.data[i + 1]!,
name: this.state.deviceData?.data[i + 2]!,
cmd: this.state.deviceData?.data[i + 3]!,
cmd: this.state.deviceData?.data[i + 3]!
}
});
}
};
noDevices = () => {
return this.props.data.devices.length === 0;
@@ -166,22 +207,41 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
{!this.noDevices() && (
<Table
size="small"
padding={isWidthDown("xs", width!) ? "none" : "default"}
padding={isWidthDown('xs', width!) ? 'none' : 'default'}
>
<TableBody>
{data.devices.sort(compareDevices).map((device) => (
<TableRow hover key={device.id} onClick={() => this.handleRowClick(device)}>
<TableRow
hover
key={device.id}
onClick={() => this.handleRowClick(device)}
>
<TableCell>
<CustomTooltip
title={"DeviceID:0x" + ("00" + device.deviceid.toString(16).toUpperCase()).slice(-2) + " ProductID:" + device.productid + " Version:" + device.version}
title={
'DeviceID:0x' +
(
'00' + device.deviceid.toString(16).toUpperCase()
).slice(-2) +
' ProductID:' +
device.productid +
' Version:' +
device.version
}
placement="right-end"
>
<Button startIcon={<ListIcon />} size="small" variant="outlined">
<Button
startIcon={<ListIcon />}
size="small"
variant="outlined"
>
{device.type}
</Button>
</CustomTooltip>
</TableCell>
<TableCell align="right">{device.brand + " " + device.name} </TableCell>
<TableCell align="right">
{device.brand + ' ' + device.name}{' '}
</TableCell>
</TableRow>
))}
</TableBody>
@@ -191,10 +251,13 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
<Box
bgcolor="error.main"
color="error.contrastText"
p={2} mt={2} mb={2}
p={2}
mt={2}
mb={2}
>
<Typography variant="body1">
No EMS devices found. Check the connections and for possible Tx errors.
No EMS devices found. Check the connections and for possible Tx
errors.
</Typography>
</Box>
)}
@@ -255,14 +318,25 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
>
<DialogTitle>Confirm Scan Devices</DialogTitle>
<DialogContent dividers>
Are you sure you want to initiate a scan on the EMS bus for all new devices?
Are you sure you want to initiate a scan on the EMS bus for all new
devices?
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={this.onScanDevicesRejected} color="secondary">
<Button
variant="contained"
onClick={this.onScanDevicesRejected}
color="secondary"
>
Cancel
</Button>
<Button
startIcon={<RefreshIcon />} variant="contained" onClick={this.onScanDevicesConfirmed} disabled={this.state.processing} color="primary" autoFocus>
startIcon={<RefreshIcon />}
variant="contained"
onClick={this.onScanDevicesConfirmed}
disabled={this.state.processing}
color="primary"
autoFocus
>
Start Scan
</Button>
</DialogActions>
@@ -283,17 +357,17 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
redirectingAuthorizedFetch(SCANDEVICES_ENDPOINT)
.then((response) => {
if (response.status === 200) {
this.props.enqueueSnackbar("Device scan is starting...", {
variant: "info",
this.props.enqueueSnackbar('Device scan is starting...', {
variant: 'info'
});
this.setState({ processing: false, confirmScanDevices: false });
} else {
throw Error("Invalid status code: " + response.status);
throw Error('Invalid status code: ' + response.status);
}
})
.catch((error) => {
this.props.enqueueSnackbar(error.message || "Problem with scan", {
variant: "error",
this.props.enqueueSnackbar(error.message || 'Problem with scan', {
variant: 'error'
});
this.setState({ processing: false, confirmScanDevices: false });
});
@@ -302,25 +376,25 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
handleRowClick = (device: any) => {
this.setState({ selectedDevice: device.id, deviceData: undefined });
redirectingAuthorizedFetch(DEVICE_DATA_ENDPOINT, {
method: "POST",
method: 'POST',
body: JSON.stringify({ id: device.id }),
headers: {
"Content-Type": "application/json",
},
'Content-Type': 'application/json'
}
})
.then((response) => {
if (response.status === 200) {
return response.json();
}
throw Error("Unexpected response code: " + response.status);
throw Error('Unexpected response code: ' + response.status);
})
.then((json) => {
this.setState({ deviceData: json });
})
.catch((error) => {
this.props.enqueueSnackbar(
error.message || "Problem getting device data",
{ variant: "error" }
error.message || 'Problem getting device data',
{ variant: 'error' }
);
this.setState({ deviceData: undefined });
});
@@ -351,10 +425,9 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
<TableContainer>
<Table
size="small"
padding={isWidthDown("xs", width!) ? "none" : "default"}
padding={isWidthDown('xs', width!) ? 'none' : 'default'}
>
<TableHead>
</TableHead>
<TableHead></TableHead>
<TableBody>
{deviceData.data.map((item, i) => {
if (i % 4) {
@@ -362,19 +435,30 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
} else {
return (
<TableRow hover key={i}>
<TableCell padding="checkbox" style={{ width: 18 }} >
<TableCell padding="checkbox" style={{ width: 18 }}>
{deviceData.data[i + 3] && me.admin && (
<CustomTooltip title="change value" placement="left-end"
<CustomTooltip
title="change value"
placement="left-end"
>
<IconButton edge="start" size="small" aria-label="Edit"
onClick={() => this.sendCommand(i)}>
<IconButton
edge="start"
size="small"
aria-label="Edit"
onClick={() => this.sendCommand(i)}
>
<EditIcon color="primary" fontSize="small" />
</IconButton>
</CustomTooltip>
)}
</TableCell>
<TableCell padding="none" component="th" scope="row">{deviceData.data[i + 2]}</TableCell>
<TableCell padding="none" align="right">{deviceData.data[i]}{formatUnit(deviceData.data[i + 1])}</TableCell>
<TableCell padding="none" component="th" scope="row">
{deviceData.data[i + 2]}
</TableCell>
<TableCell padding="none" align="right">
{deviceData.data[i]}
{formatUnit(deviceData.data[i + 1])}
</TableCell>
</TableRow>
);
}
@@ -390,7 +474,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
</Typography>
</Box>
)}
</Fragment >
</Fragment>
);
}
@@ -405,26 +489,34 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
<br></br>
<Box display="flex" flexWrap="wrap">
<Box flexGrow={1} padding={1}>
<FormButton startIcon={<RefreshIcon />} variant="contained" color="secondary" onClick={this.props.loadData} >
<FormButton
startIcon={<RefreshIcon />}
variant="contained"
color="secondary"
onClick={this.props.loadData}
>
Refresh
</FormButton>
</Box>
<Box flexWrap="none" padding={1} whiteSpace="nowrap">
<FormButton startIcon={<RefreshIcon />} variant="contained" onClick={this.onScanDevices} >
<FormButton
startIcon={<RefreshIcon />}
variant="contained"
onClick={this.onScanDevices}
>
Scan Devices
</FormButton>
</Box>
</Box>
{this.renderScanDevicesDialog()}
{
devicevalue &&
{devicevalue && (
<ValueForm
devicevalue={devicevalue}
onDoneEditing={this.doneEditingValue}
onCancelEditing={this.cancelEditingValue}
handleValueChange={this.handleValueChange}
/>
}
)}
</Fragment>
);
}