feat: board profiles (#11)

This commit is contained in:
proddy
2021-03-22 21:12:19 +01:00
parent 273efbcb65
commit b996c4dcf6
13 changed files with 415 additions and 363 deletions

View File

@@ -1,5 +1,5 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { TextValidator, SelectValidator, ValidatorForm } from 'react-material-ui-form-validator'; import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator';
import { Checkbox, List, ListItem, ListItemText, ListItemAvatar, ListItemSecondaryAction } from '@material-ui/core'; import { Checkbox, List, ListItem, ListItemText, ListItemAvatar, ListItemSecondaryAction } from '@material-ui/core';
@@ -9,7 +9,6 @@ import LockIcon from '@material-ui/icons/Lock';
import LockOpenIcon from '@material-ui/icons/LockOpen'; import LockOpenIcon from '@material-ui/icons/LockOpen';
import DeleteIcon from '@material-ui/icons/Delete'; import DeleteIcon from '@material-ui/icons/Delete';
import SaveIcon from '@material-ui/icons/Save'; import SaveIcon from '@material-ui/icons/Save';
import MenuItem from '@material-ui/core/MenuItem';
import { RestFormProps, PasswordValidator, BlockFormControlLabel, FormActions, FormButton } from '../components'; import { RestFormProps, PasswordValidator, BlockFormControlLabel, FormActions, FormButton } from '../components';
import { isIP, isHostname, optional } from '../validators'; import { isIP, isHostname, optional } from '../validators';
@@ -34,7 +33,6 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
ssid: selectedNetwork.ssid, ssid: selectedNetwork.ssid,
password: "", password: "",
hostname: props.data.hostname, hostname: props.data.hostname,
ethernet_profile: 0,
static_ip_config: false, static_ip_config: false,
} }
props.setData(networkSettings); props.setData(networkSettings);
@@ -119,17 +117,6 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
onChange={handleValueChange('hostname')} onChange={handleValueChange('hostname')}
margin="normal" margin="normal"
/> />
<SelectValidator name="ems_bus_id"
label="Ethernet Profile"
value={data.ethernet_profile}
fullWidth
variant="outlined"
onChange={handleValueChange('ethernet_profile')}
margin="normal">
<MenuItem value={0}>None (wifi only)</MenuItem>
<MenuItem value={1}>Profile 1 (LAN8720)</MenuItem>
<MenuItem value={2}>Profile 2 (TLK110)</MenuItem>
</SelectValidator>
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox

View File

@@ -36,7 +36,6 @@ export interface NetworkSettings {
ssid: string; ssid: string;
password: string; password: string;
hostname: string; hostname: string;
ethernet_profile: number;
static_ip_config: boolean; static_ip_config: boolean;
local_ip?: string; local_ip?: string;
gateway_ip?: string; gateway_ip?: string;

View File

@@ -2,40 +2,19 @@ import React, { Component, Fragment } from "react";
import { withStyles, Theme, createStyles } from "@material-ui/core/styles"; import { withStyles, Theme, createStyles } from "@material-ui/core/styles";
import { import {
Table, Table, TableBody, TableCell, TableHead, TableRow, TableContainer, withWidth, WithWidthProps, isWidthDown,
TableBody, Button, Tooltip, DialogTitle, DialogContent, DialogActions, Box, Dialog, Typography
TableCell,
TableHead,
TableRow,
TableContainer,
withWidth,
WithWidthProps,
isWidthDown,
Button,
Tooltip,
DialogTitle,
DialogContent,
DialogActions,
Box,
Dialog,
Typography,
} from "@material-ui/core"; } from "@material-ui/core";
import RefreshIcon from "@material-ui/icons/Refresh"; import RefreshIcon from "@material-ui/icons/Refresh";
import ListIcon from "@material-ui/icons/List"; import ListIcon from "@material-ui/icons/List";
import { import { redirectingAuthorizedFetch, withAuthenticatedContext, AuthenticatedContextProps } from "../authentication";
redirectingAuthorizedFetch,
withAuthenticatedContext,
AuthenticatedContextProps,
} from "../authentication";
import { RestFormProps, FormButton } from "../components"; import { RestFormProps, FormButton } from "../components";
import { EMSESPDevices, EMSESPDeviceData, Device } from "./EMSESPtypes"; import { EMSESPDevices, EMSESPDeviceData, Device } from "./EMSESPtypes";
import { ENDPOINT_ROOT } from "../api"; import { ENDPOINT_ROOT } from "../api";
export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices"; export const SCANDEVICES_ENDPOINT = ENDPOINT_ROOT + "scanDevices";
export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + "deviceData"; export const DEVICE_DATA_ENDPOINT = ENDPOINT_ROOT + "deviceData";
@@ -73,7 +52,7 @@ type EMSESPDevicesFormProps = RestFormProps<EMSESPDevices> &
function formatTemp(t: string) { function formatTemp(t: string) {
if (t == null) { if (t == null) {
return "(not available)"; return "n/a";
} }
return t + " °C"; return t + " °C";
} }
@@ -85,10 +64,7 @@ function formatTemp(t: string) {
return " " + u; return " " + u;
} }
class EMSESPDevicesForm extends Component< class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesFormState> {
EMSESPDevicesFormProps,
EMSESPDevicesFormState
> {
state: EMSESPDevicesFormState = { state: EMSESPDevicesFormState = {
confirmScanDevices: false, confirmScanDevices: false,
processing: false, processing: false,
@@ -106,7 +82,7 @@ class EMSESPDevicesForm extends Component<
return (this.state.deviceData?.data || []).length === 0; return (this.state.deviceData?.data || []).length === 0;
}; };
createDeviceItems() { renderDeviceItems() {
const { width, data } = this.props; const { width, data } = this.props;
return ( return (
<TableContainer> <TableContainer>
@@ -186,7 +162,7 @@ class EMSESPDevicesForm extends Component<
); );
} }
createSensorItems() { renderSensorItems() {
const { data } = this.props; const { data } = this.props;
return ( return (
<TableContainer> <TableContainer>
@@ -379,9 +355,9 @@ class EMSESPDevicesForm extends Component<
return ( return (
<Fragment> <Fragment>
<br></br> <br></br>
{this.createDeviceItems()} {this.renderDeviceItems()}
{this.renderDeviceData()} {this.renderDeviceData()}
{this.createSensorItems()} {this.renderSensorItems()}
<br></br> <br></br>
<Box display="flex" flexWrap="wrap"> <Box display="flex" flexWrap="wrap">
<Box flexGrow={1} padding={1}> <Box flexGrow={1} padding={1}>

View File

@@ -1,14 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { ValidatorForm, TextValidator, SelectValidator } from 'react-material-ui-form-validator'; // import { Container } from '@material-ui/core';
import { Checkbox, Typography, Box, Link } from '@material-ui/core';
import SaveIcon from '@material-ui/icons/Save';
import MenuItem from '@material-ui/core/MenuItem';
import { ENDPOINT_ROOT } from '../api'; import { ENDPOINT_ROOT } from '../api';
import { restController, RestControllerProps, RestFormLoader, RestFormProps, FormActions, FormButton, BlockFormControlLabel, SectionContent } from '../components'; import EMSESPSettingsForm from './EMSESPSettingsForm';
import { isIP, optional } from '../validators'; import { restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
import { EMSESPSettings } from './EMSESPtypes'; import { EMSESPSettings } from './EMSESPtypes';
@@ -19,303 +15,24 @@ type EMSESPSettingsControllerProps = RestControllerProps<EMSESPSettings>;
class EMSESPSettingsController extends Component<EMSESPSettingsControllerProps> { class EMSESPSettingsController extends Component<EMSESPSettingsControllerProps> {
componentDidMount() { componentDidMount() {
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP));
this.props.loadData(); this.props.loadData();
} }
render() { render() {
return ( return (
<SectionContent title='EMS-ESP Settings' titleGutter> // <Container maxWidth="md" disableGutters>
<SectionContent title='' titleGutter>
<RestFormLoader <RestFormLoader
{...this.props} {...this.props}
render={props => ( render={formProps => (
<EMSESPSettingsControllerForm {...props} /> <EMSESPSettingsForm {...formProps} />
)} )}
/> />
</SectionContent> </SectionContent>
// </Container>
) )
} }
} }
export default restController(EMSESP_SETTINGS_ENDPOINT, EMSESPSettingsController); export default restController(EMSESP_SETTINGS_ENDPOINT, EMSESPSettingsController);
type EMSESPSettingsControllerFormProps = RestFormProps<EMSESPSettings>;
function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps) {
const { data, saveData, handleValueChange } = props;
return (
<ValidatorForm onSubmit={saveData}>
<Box bgcolor="info.main" p={2} mt={2} mb={2}>
<Typography variant="body1">
Change the default settings on this page. For help click <Link target="_blank" href="https://emsesp.github.io/docs/#/Configure-firmware?id=settings" color="primary">{'here'}</Link>.
</Typography>
</Box>
<br></br>
<Typography variant="h6" color="primary" >
EMS Bus
</Typography>
<SelectValidator name="tx_mode"
label="Tx Mode"
value={data.tx_mode}
fullWidth
variant="outlined"
onChange={handleValueChange('tx_mode')}
margin="normal">
<MenuItem value={0}>0 - Off</MenuItem>
<MenuItem value={1}>1 - Default</MenuItem>
<MenuItem value={2}>2 - EMS+</MenuItem>
<MenuItem value={3}>3 - HT3</MenuItem>
<MenuItem value={4}>4 - Hardware</MenuItem>
</SelectValidator>
<SelectValidator name="ems_bus_id"
label="Bus ID"
value={data.ems_bus_id}
fullWidth
variant="outlined"
onChange={handleValueChange('ems_bus_id')}
margin="normal">
<MenuItem value={0x0B}>Service Key (0x0B)</MenuItem>
<MenuItem value={0x0D}>Modem (0x0D)</MenuItem>
<MenuItem value={0x0A}>Terminal (0x0A)</MenuItem>
<MenuItem value={0x0F}>Time Module (0x0F)</MenuItem>
<MenuItem value={0x12}>Alarm Module (0x12)</MenuItem>
</SelectValidator>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Rx GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="rx_gpio"
label="Rx GPIO pin"
fullWidth
variant="outlined"
value={data.rx_gpio}
type="number"
onChange={handleValueChange('rx_gpio')}
margin="normal"
/>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Tx GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="tx_gpio"
label="Tx GPIO pin"
fullWidth
variant="outlined"
value={data.tx_gpio}
type="number"
onChange={handleValueChange('tx_gpio')}
margin="normal"
/>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:120']}
errorMessages={['Tx delay is required', "Must be a number", "Must be 0 or higher", "Max value is 120"]}
name="tx_delay"
label="Tx delayed start (seconds)"
fullWidth
variant="outlined"
value={data.tx_delay}
type="number"
onChange={handleValueChange('tx_delay')}
margin="normal"
/>
<br></br>
<Typography variant="h6" color="primary" >
External Button
</Typography>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Button GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="pbutton_gpio"
label="Button GPIO pin"
fullWidth
variant="outlined"
value={data.pbutton_gpio}
type="number"
onChange={handleValueChange('pbutton_gpio')}
margin="normal"
/>
<br></br>
<Typography variant="h6" color="primary" >
Dallas Sensor
</Typography>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Dallas GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="dallas_gpio"
label="Dallas GPIO pin (0=none)"
fullWidth
variant="outlined"
value={data.dallas_gpio}
type="number"
onChange={handleValueChange('dallas_gpio')}
margin="normal"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.dallas_parasite}
onChange={handleValueChange('dallas_parasite')}
value="dallas_parasite"
/>
}
label="Dallas Parasite Mode"
/>
<br></br>
<Typography variant="h6" color="primary" >
LED
</Typography>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['LED GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="led_gpio"
label="LED GPIO pin (0=none)"
fullWidth
variant="outlined"
value={data.led_gpio}
type="number"
onChange={handleValueChange('led_gpio')}
margin="normal"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.hide_led}
onChange={handleValueChange('hide_led')}
value="hide_led"
/>
}
label="Invert/Hide LED"
/>
<br></br>
<Typography variant="h6" color="primary" >
Shower
</Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.shower_timer}
onChange={handleValueChange('shower_timer')}
value="shower_timer"
/>
}
label="Shower Timer"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.shower_alert}
onChange={handleValueChange('shower_alert')}
value="shower_alert"
/>
}
label="Shower Alert"
/>
<br></br>
<Typography variant="h6" color="primary" >
API
</Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.api_enabled}
onChange={handleValueChange('api_enabled')}
value="api_enabled"
/>
}
label="Allow WEB API to write commands"
/>
<br></br>
<Typography variant="h6" color="primary" >
Syslog
</Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.syslog_enabled}
onChange={handleValueChange('syslog_enabled')}
value="syslog_enabled"
/>
}
label="Enable Syslog"
/>
<TextValidator
validators={['isOptionalIP']}
errorMessages={["Not a valid IP address"]}
name="syslog_host"
label="Syslog IP"
fullWidth
variant="outlined"
value={data.syslog_host}
onChange={handleValueChange('syslog_host')}
margin="normal"
/>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
errorMessages={['Port is required', "Must be a number", "Must be greater than 0 ", "Max value is 65535"]}
name="syslog_port"
label="Syslog Port (default 514)"
fullWidth
variant="outlined"
value={data.syslog_port}
type="number"
onChange={handleValueChange('syslog_port')}
margin="normal"
/>
<SelectValidator name="syslog_level"
label="Syslog Log Level"
value={data.syslog_level}
fullWidth
variant="outlined"
onChange={handleValueChange('syslog_level')}
margin="normal">
<MenuItem value={-1}>OFF</MenuItem>
<MenuItem value={3}>ERR</MenuItem>
<MenuItem value={5}>NOTICE</MenuItem>
<MenuItem value={6}>INFO</MenuItem>
<MenuItem value={7}>DEBUG</MenuItem>
<MenuItem value={8}>ALL</MenuItem>
</SelectValidator>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
errorMessages={['Syslog Mark is required', "Must be a number", "Must be 0 or higher", "Max value is 10"]}
name="syslog_mark_interval"
label="Syslog Mark Interval (seconds, 0=off)"
fullWidth
variant="outlined"
value={data.syslog_mark_interval}
type="number"
onChange={handleValueChange('syslog_mark_interval')}
margin="normal"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.trace_raw}
onChange={handleValueChange('trace_raw')}
value="trace_raw"
/>
}
label="Trace EMS telegrams in raw format"
/>
<br></br>
<Typography variant="h6" color="primary" >
Analog Input
</Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.analog_enabled}
onChange={handleValueChange('analog_enabled')}
value="analog_enabled"
/>
}
label="Enable ADC"
/>
<br></br>
<FormActions>
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
Save
</FormButton>
</FormActions>
</ValidatorForm>
);
}

View File

@@ -0,0 +1,371 @@
import React from 'react';
import { ValidatorForm, TextValidator, SelectValidator } from 'react-material-ui-form-validator';
import { Checkbox, Typography, Box, Link, withWidth, WithWidthProps } from '@material-ui/core';
import SaveIcon from '@material-ui/icons/Save';
import MenuItem from '@material-ui/core/MenuItem';
import Grid from '@material-ui/core/Grid';
import { RestFormProps, FormActions, FormButton, BlockFormControlLabel } from '../components';
import { isIP, optional } from '../validators';
import { EMSESPSettings } from './EMSESPtypes';
type EMSESPSettingsFormProps = RestFormProps<EMSESPSettings> & WithWidthProps;
class EMSESPSettingsForm extends React.Component<EMSESPSettingsFormProps> {
componentDidMount() {
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP));
}
/*
handleSliderChange = (name: keyof LedSettings) => (event: React.ChangeEvent<{}>, value: number | number[]) => {
const { setData } = this.props;
setData({ ...this.props.data!, [name]: value });
}
*/
render() {
const { data, saveData, handleValueChange } = this.props;
return (
<ValidatorForm onSubmit={saveData}>
<Box bgcolor="info.main" p={2} mt={2} mb={2}>
<Typography variant="body1">
Modify any EMS-ESP settings on this page. For help go to the <Link target="_blank" href="https://emsesp.github.io/docs/#/Configure-firmware32?id=ems-esp-settings" color="primary">{'wiki'}</Link>.
</Typography>
</Box>
<br></br>
<Typography variant="h6" color="primary" >
EMS Bus
</Typography>
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
<Grid item xs={5}>
<SelectValidator name="tx_mode"
label="Tx Mode"
value={data.tx_mode}
fullWidth
variant="outlined"
onChange={handleValueChange('tx_mode')}
margin="normal">
<MenuItem value={0}>Off</MenuItem>
<MenuItem value={1}>EMS</MenuItem>
<MenuItem value={2}>EMS+</MenuItem>
<MenuItem value={3}>HT3</MenuItem>
<MenuItem value={4}>Hardware</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={6}>
<SelectValidator name="ems_bus_id"
label="Bus ID"
value={data.ems_bus_id}
fullWidth
variant="outlined"
onChange={handleValueChange('ems_bus_id')}
margin="normal">
<MenuItem value={0x0B}>Service Key (0x0B)</MenuItem>
<MenuItem value={0x0D}>Modem (0x0D)</MenuItem>
<MenuItem value={0x0A}>Terminal (0x0A)</MenuItem>
<MenuItem value={0x0F}>Time Module (0x0F)</MenuItem>
<MenuItem value={0x12}>Alarm Module (0x12)</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={6}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:120']}
errorMessages={['Tx delay is required', "Must be a number", "Must be 0 or higher", "Max value is 120"]}
name="tx_delay"
label="Tx start delay (seconds)"
fullWidth
variant="outlined"
value={data.tx_delay}
type="number"
onChange={handleValueChange('tx_delay')}
margin="normal"
/>
</Grid>
</Grid>
<br></br>
<Typography variant="h6" color="primary" >
Board Profile
</Typography>
<Box color="warning.main" p={0} mt={0} mb={0}>
<Typography variant="body2">
<i>Choose from a pre-configured board layout to automatically set the GPIO pins</i>
</Typography>
</Box>
<SelectValidator name="board_profile"
label="Board Profile"
value={data.board_profile}
fullWidth
variant="outlined"
onChange={handleValueChange('board_profile')}
margin="normal">
<MenuItem value={1}>Gateway S32</MenuItem>
<MenuItem value={2}>Gateway E32 (LAN8720)</MenuItem>
<MenuItem value={3}>NodeMCU 32S</MenuItem>
<MenuItem value={4}>Lolin D32</MenuItem>
<MenuItem value={5}>Olimex ESP32 Gateway (LAN8720)</MenuItem>
<MenuItem value={6}>Ethernet (TLK110)</MenuItem>
<MenuItem value={0}>Custom...</MenuItem>
</SelectValidator>
{ (data.board_profile === 0) &&
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
<Grid item xs={4}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Rx GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="rx_gpio"
label="Rx GPIO"
fullWidth
variant="outlined"
value={data.rx_gpio}
type="number"
onChange={handleValueChange('rx_gpio')}
margin="normal"
/>
</Grid>
<Grid item xs={4}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Tx GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="tx_gpio"
label="Tx GPIO"
fullWidth
variant="outlined"
value={data.tx_gpio}
type="number"
onChange={handleValueChange('tx_gpio')}
margin="normal"
/>
</Grid>
<Grid item xs={4}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Button GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="pbutton_gpio"
label="Button GPIO"
fullWidth
variant="outlined"
value={data.pbutton_gpio}
type="number"
onChange={handleValueChange('pbutton_gpio')}
margin="normal"
/>
</Grid>
<Grid item xs={4}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['Dallas GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="dallas_gpio"
label="Dallas GPIO (0=none)"
fullWidth
variant="outlined"
value={data.dallas_gpio}
type="number"
onChange={handleValueChange('dallas_gpio')}
margin="normal"
/>
</Grid>
<Grid item xs={4}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:40']}
errorMessages={['LED GPIO is required', "Must be a number", "Must be 0 or higher", "Max value is 40"]}
name="led_gpio"
label="LED GPIO (0=none)"
fullWidth
variant="outlined"
value={data.led_gpio}
type="number"
onChange={handleValueChange('led_gpio')}
margin="normal"
/>
</Grid>
</Grid>
}
<br></br>
<Typography variant="h6" color="primary" >
Options
</Typography>
{ data.dallas_gpio !== 0 &&
<BlockFormControlLabel
control={
<Checkbox
checked={data.dallas_parasite}
onChange={handleValueChange('dallas_parasite')}
value="dallas_parasite"
/>
}
label="Enable Dallas parasite mode"
/>
}
{ data.led_gpio !== 0 &&
<BlockFormControlLabel
control={
<Checkbox
checked={data.hide_led}
onChange={handleValueChange('hide_led')}
value="hide_led"
/>
}
label="Invert LED"
/>
}
<Grid container spacing={0} direction="row" justify="flex-start" alignItems="flex-start">
<BlockFormControlLabel
control={
<Checkbox
checked={data.shower_timer}
onChange={handleValueChange('shower_timer')}
value="shower_timer"
/>
}
label="Shower Timer"
/>
{/* <BlockFormControlLabel
control={
<Checkbox
checked={data.shower_alert}
onChange={handleValueChange('shower_alert')}
value="shower_alert"
/>
}
label="Shower Alert"
/> */}
</Grid>
<BlockFormControlLabel
control={
<Checkbox
checked={data.api_enabled}
onChange={handleValueChange('api_enabled')}
value="api_enabled"
/>
}
label="Enable API write commands"
/>
<BlockFormControlLabel
control={
<Checkbox
checked={data.analog_enabled}
onChange={handleValueChange('analog_enabled')}
value="analog_enabled"
/>
}
label="Enable ADC"
/>
<br></br>
<Typography variant="h6" color="primary" >
Syslog
</Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.syslog_enabled}
onChange={handleValueChange('syslog_enabled')}
value="syslog_enabled"
/>
}
label="Enable Syslog"
/>
{ data.syslog_enabled &&
<Grid container spacing={1} direction="row" justify="flex-start" alignItems="flex-start">
<Grid item xs={5}>
<TextValidator
validators={['isOptionalIP']}
errorMessages={["Not a valid IP address"]}
name="syslog_host"
label="IP"
fullWidth
variant="outlined"
value={data.syslog_host}
onChange={handleValueChange('syslog_host')}
margin="normal"
/>
</Grid>
<Grid item xs={6}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
errorMessages={['Port is required', "Must be a number", "Must be greater than 0 ", "Max value is 65535"]}
name="syslog_port"
label="Port"
fullWidth
variant="outlined"
value={data.syslog_port}
type="number"
onChange={handleValueChange('syslog_port')}
margin="normal"
/>
</Grid>
<Grid item xs={5}>
<SelectValidator name="syslog_level"
label="Log Level"
value={data.syslog_level}
fullWidth
variant="outlined"
onChange={handleValueChange('syslog_level')}
margin="normal">
<MenuItem value={-1}>OFF</MenuItem>
<MenuItem value={3}>ERR</MenuItem>
<MenuItem value={5}>NOTICE</MenuItem>
<MenuItem value={6}>INFO</MenuItem>
<MenuItem value={7}>DEBUG</MenuItem>
<MenuItem value={8}>ALL</MenuItem>
</SelectValidator>
</Grid>
<Grid item xs={6}>
<TextValidator
validators={['required', 'isNumber', 'minNumber:0', 'maxNumber:65535']}
errorMessages={['Syslog Mark is required', "Must be a number", "Must be 0 or higher", "Max value is 10"]}
name="syslog_mark_interval"
label="Mark Interval seconds (0=off)"
fullWidth
variant="outlined"
value={data.syslog_mark_interval}
type="number"
onChange={handleValueChange('syslog_mark_interval')}
margin="normal"
/>
</Grid>
<BlockFormControlLabel
control={
<Checkbox
checked={data.trace_raw}
onChange={handleValueChange('trace_raw')}
value="trace_raw"
/>
}
label="Output EMS telegrams in raw format"
/>
</Grid>
}
<br></br>
<FormActions>
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
Save
</FormButton>
</FormActions>
</ValidatorForm >
);
}
}
export default withWidth()(EMSESPSettingsForm);

View File

@@ -20,6 +20,7 @@ export interface EMSESPSettings {
analog_enabled: boolean; analog_enabled: boolean;
pbutton_gpio: number; pbutton_gpio: number;
trace_raw: boolean; trace_raw: boolean;
board_profile: number;
} }
export enum busConnectionStatus { export enum busConnectionStatus {

View File

@@ -31,7 +31,6 @@ class NetworkSettings {
String password; String password;
String hostname; String hostname;
bool staticIPConfig; bool staticIPConfig;
uint8_t ethernet_profile;
// optional configuration for static IP address // optional configuration for static IP address
IPAddress localIP; IPAddress localIP;
@@ -46,7 +45,6 @@ class NetworkSettings {
root["password"] = settings.password; root["password"] = settings.password;
root["hostname"] = settings.hostname; root["hostname"] = settings.hostname;
root["static_ip_config"] = settings.staticIPConfig; root["static_ip_config"] = settings.staticIPConfig;
root["ethernet_profile"] = settings.ethernet_profile;
// extended settings // extended settings
JsonUtils::writeIP(root, "local_ip", settings.localIP); JsonUtils::writeIP(root, "local_ip", settings.localIP);
@@ -61,7 +59,6 @@ class NetworkSettings {
settings.password = root["password"] | FACTORY_WIFI_PASSWORD; settings.password = root["password"] | FACTORY_WIFI_PASSWORD;
settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME; settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME;
settings.staticIPConfig = root["static_ip_config"] | false; settings.staticIPConfig = root["static_ip_config"] | false;
settings.ethernet_profile = root["ethernet_profile"] | 0; // no ethernet
// extended settings // extended settings
JsonUtils::readIP(root, "local_ip", settings.localIP); JsonUtils::readIP(root, "local_ip", settings.localIP);

View File

@@ -49,7 +49,7 @@ class DummySettings {
String staticIPConfig = ""; String staticIPConfig = "";
String dnsIP1 = ""; String dnsIP1 = "";
String dnsIP2 = ""; String dnsIP2 = "";
uint8_t ethernet_profile = 0; uint8_t board_profile = 0;
uint16_t publish_time_boiler = 10; uint16_t publish_time_boiler = 10;
uint16_t publish_time_thermostat = 10; uint16_t publish_time_thermostat = 10;
uint16_t publish_time_solar = 10; uint16_t publish_time_solar = 10;

View File

@@ -50,6 +50,7 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) {
root["api_enabled"] = settings.api_enabled; root["api_enabled"] = settings.api_enabled;
root["analog_enabled"] = settings.analog_enabled; root["analog_enabled"] = settings.analog_enabled;
root["pbutton_gpio"] = settings.pbutton_gpio; root["pbutton_gpio"] = settings.pbutton_gpio;
root["board_profile"] = settings.board_profile;
} }
StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) { StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) {
@@ -132,6 +133,9 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
// doesn't need any follow-up actions // doesn't need any follow-up actions
settings.api_enabled = root["api_enabled"] | EMSESP_DEFAULT_API_ENABLED; settings.api_enabled = root["api_enabled"] | EMSESP_DEFAULT_API_ENABLED;
// board profiles
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
return StateUpdateResult::CHANGED; return StateUpdateResult::CHANGED;
} }

View File

@@ -42,6 +42,7 @@
#define EMSESP_DEFAULT_API_ENABLED false // turn off, because its insecure #define EMSESP_DEFAULT_API_ENABLED false // turn off, because its insecure
#define EMSESP_DEFAULT_BOOL_FORMAT 1 // on/off #define EMSESP_DEFAULT_BOOL_FORMAT 1 // on/off
#define EMSESP_DEFAULT_ANALOG_ENABLED false #define EMSESP_DEFAULT_ANALOG_ENABLED false
#define EMSESP_DEFAULT_BOARD_PROFILE 0 // default ESP32
// Default GPIO PIN definitions // Default GPIO PIN definitions
#if defined(ESP32) #if defined(ESP32)
@@ -84,6 +85,7 @@ class WebSettings {
bool api_enabled; bool api_enabled;
bool analog_enabled; bool analog_enabled;
uint8_t pbutton_gpio; uint8_t pbutton_gpio;
uint8_t board_profile;
static void read(WebSettings & settings, JsonObject & root); static void read(WebSettings & settings, JsonObject & root);
static StateUpdateResult update(JsonObject & root, WebSettings & settings); static StateUpdateResult update(JsonObject & root, WebSettings & settings);

View File

@@ -169,12 +169,14 @@ void System::get_settings() {
// LED // LED
hide_led_ = settings.hide_led; hide_led_ = settings.hide_led;
led_gpio_ = settings.led_gpio; led_gpio_ = settings.led_gpio;
// BOARD profile
board_profile_ = settings.board_profile;
}); });
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) { EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
hostname(networkSettings.hostname.c_str()); hostname(networkSettings.hostname.c_str());
LOG_INFO(F("System %s booted (EMS-ESP version %s)"), networkSettings.hostname.c_str(), EMSESP_APP_VERSION); // print boot message LOG_INFO(F("System %s booted (EMS-ESP version %s)"), networkSettings.hostname.c_str(), EMSESP_APP_VERSION); // print boot message
ethernet_profile_ = networkSettings.ethernet_profile;
}); });
} }
@@ -284,7 +286,6 @@ void System::button_init(bool refresh) {
} }
// Allow 0 for Boot-button on NodeMCU-32s? // Allow 0 for Boot-button on NodeMCU-32s?
// if (pbutton_gpio_) {
if (!myPButton_.init(pbutton_gpio_, HIGH)) { if (!myPButton_.init(pbutton_gpio_, HIGH)) {
LOG_INFO(F("External multi-functional button not detected")); LOG_INFO(F("External multi-functional button not detected"));
} else { } else {
@@ -295,7 +296,6 @@ void System::button_init(bool refresh) {
myPButton_.onDblClick(BUTTON_DblClickDelay, button_OnDblClick); myPButton_.onDblClick(BUTTON_DblClickDelay, button_OnDblClick);
myPButton_.onLongPress(BUTTON_LongPressDelay, button_OnLongPress); myPButton_.onLongPress(BUTTON_LongPressDelay, button_OnLongPress);
myPButton_.onVLongPress(BUTTON_VLongPressDelay, button_OnVLongPress); myPButton_.onVLongPress(BUTTON_VLongPressDelay, button_OnVLongPress);
// }
} }
// set the LED to on or off when in normal operating mode // set the LED to on or off when in normal operating mode
@@ -454,7 +454,7 @@ void System::network_init(bool refresh) {
// check ethernet profile // check ethernet profile
// ethernet uses lots of additional memory so we only start it when it's explicitly set in the config // ethernet uses lots of additional memory so we only start it when it's explicitly set in the config
if (ethernet_profile_ == 0) { if (board_profile_ == 0) {
return; return;
} }
@@ -465,7 +465,7 @@ void System::network_init(bool refresh) {
eth_phy_type_t type; // Type of the Ethernet PHY (LAN8720 or TLK110) eth_phy_type_t type; // Type of the Ethernet PHY (LAN8720 or TLK110)
eth_clock_mode_t clock_mode; // ETH_CLOCK_GPIO0_IN or ETH_CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO16_OUT, ETH_CLOCK_GPIO17_OUT for 50Hz inverted clock eth_clock_mode_t clock_mode; // ETH_CLOCK_GPIO0_IN or ETH_CLOCK_GPIO0_OUT, ETH_CLOCK_GPIO16_OUT, ETH_CLOCK_GPIO17_OUT for 50Hz inverted clock
if (ethernet_profile_ == 1) { if (board_profile_ == 1) {
// LAN8720 // LAN8720
phy_addr = 0; phy_addr = 0;
power = -1; power = -1;
@@ -473,7 +473,7 @@ void System::network_init(bool refresh) {
mdio = 18; mdio = 18;
type = ETH_PHY_LAN8720; type = ETH_PHY_LAN8720;
clock_mode = ETH_CLOCK_GPIO0_IN; clock_mode = ETH_CLOCK_GPIO0_IN;
} else if (ethernet_profile_ == 2) { } else if (board_profile_ == 2) {
// TLK110 // TLK110
phy_addr = 31; phy_addr = 31;
power = -1; power = -1;
@@ -803,10 +803,10 @@ void System::console_commands(Shell & shell, unsigned int context) {
[](Shell & shell, const std::vector<std::string> & arguments) { [](Shell & shell, const std::vector<std::string> & arguments) {
uint8_t n = Helpers::hextoint(arguments.front().c_str()); uint8_t n = Helpers::hextoint(arguments.front().c_str());
if (n <= 2) { if (n <= 2) {
EMSESP::esp8266React.getNetworkSettingsService()->update( EMSESP::webSettingsService.update(
[&](NetworkSettings & networkSettings) { [&](WebSettings & settings) {
networkSettings.ethernet_profile = n; settings.board_profile = n;
shell.printfln(F_(ethernet_option_fmt), networkSettings.ethernet_profile); shell.printfln(F_(ethernet_option_fmt), n);
return StateUpdateResult::CHANGED; return StateUpdateResult::CHANGED;
}, },
"local"); "local");
@@ -827,8 +827,6 @@ void System::console_commands(Shell & shell, unsigned int context) {
shell.printfln(F_(wifi_ssid_fmt), networkSettings.ssid.isEmpty() ? uuid::read_flash_string(F_(unset)).c_str() : networkSettings.ssid.c_str()); shell.printfln(F_(wifi_ssid_fmt), networkSettings.ssid.isEmpty() ? uuid::read_flash_string(F_(unset)).c_str() : networkSettings.ssid.c_str());
shell.print(F(" ")); shell.print(F(" "));
shell.printfln(F_(wifi_password_fmt), networkSettings.ssid.isEmpty() ? F_(unset) : F_(asterisks)); shell.printfln(F_(wifi_password_fmt), networkSettings.ssid.isEmpty() ? F_(unset) : F_(asterisks));
shell.print(F(" "));
shell.printfln(F_(ethernet_option_fmt), networkSettings.ethernet_profile);
}); });
}); });

View File

@@ -143,7 +143,7 @@ class System {
uint8_t led_gpio_; uint8_t led_gpio_;
bool syslog_enabled_; bool syslog_enabled_;
bool analog_enabled_; bool analog_enabled_;
uint8_t ethernet_profile_; uint8_t board_profile_;
uint8_t pbutton_gpio_; uint8_t pbutton_gpio_;
int8_t syslog_level_; int8_t syslog_level_;
uint32_t syslog_mark_interval_; uint32_t syslog_mark_interval_;

View File

@@ -1,2 +1,2 @@
#define EMSESP_APP_VERSION "3.0.1b1" #define EMSESP_APP_VERSION "3.0.1b2"
#define EMSESP_PLATFORM "ESP32" #define EMSESP_PLATFORM "ESP32"