mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
UI improvements in web
This commit is contained in:
@@ -5,10 +5,10 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [2.0.0 alpha]
|
## [2.0.0 beta]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- everything. See README
|
- everything. See `README.md`
|
||||||
|
|
||||||
## [1.9.5] 30-04-2020
|
## [1.9.5] 30-04-2020
|
||||||
|
|
||||||
|
|||||||
86
README.md
86
README.md
@@ -1,13 +1,19 @@
|
|||||||
# EMS-ESP version 2.0
|
# EMS-ESP version 2.0
|
||||||
|
|
||||||
|
## **Breaking changes**
|
||||||
|
|
||||||
|
- MQTT base has been removed. The hostname is only used.
|
||||||
|
|
||||||
## **New Features in v2**
|
## **New Features in v2**
|
||||||
|
|
||||||
- A new web interface using React and TypeScript that's now secure as each URL endpoint is protected by issuing a JWT which is then sent using Bearer Authentication. Using a Captive Portal in AP mode or connecting to a local wifi network.
|
- A new web interface using React and TypeScript that's now secure as each URL endpoint is protected by issuing a JWT which is then sent using Bearer Authentication. Using a Captive Portal in AP mode or connecting to a local wifi network.
|
||||||
|
|
||||||

|
<img src="media/web_settings.PNG" width=70% height=70%>
|
||||||

|
<img src="media/web_status.PNG" width=70% height=70%>
|
||||||
|
<img src="media/web_devices.PNG" width=70% height=70%>
|
||||||
|
<img src="media/web_mqtt.PNG" width=70% height=70%>
|
||||||
|
|
||||||
- A new console. Like in version 1.9 it works with both Serial and Telnet but with a rich set of commands and more intuitive with behavior similar to a Linux-style shell. It supports multiple connections and commands that alter the settings or interact directly with EMS devices are secure behind an admin password. A full list of commands is below, here are the key ones:
|
- A new console. Like in version 1.9 it works with both Serial and Telnet but with a more intuitive Linux shell like behavior. It supports multiple connections and has basic security to prevent any changes to EMS-ESP. A full list of commands is below, here are the key ones:
|
||||||
* `help` lists the commands and keywords
|
* `help` lists the commands and keywords
|
||||||
* some commands take you into a new context, a bit like a sub-menu. e.g. `system`, `thermostat`. Use `help` to show which commands this context has and `exit` or CTRL-D to get back to the root.
|
* some commands take you into a new context, a bit like a sub-menu. e.g. `system`, `thermostat`. Use `help` to show which commands this context has and `exit` or CTRL-D to get back to the root.
|
||||||
* To change a setting use the `set` command. Typing `set` shows the current settings.
|
* To change a setting use the `set` command. Typing `set` shows the current settings.
|
||||||
@@ -112,43 +118,73 @@ thermostat
|
|||||||
- See if it's easier to use timers instead of millis() based timers, using [polledTimeout](https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/BlinkPolledTimeout/BlinkPolledTimeout.ino).
|
- See if it's easier to use timers instead of millis() based timers, using [polledTimeout](https://github.com/esp8266/Arduino/blob/master/libraries/esp8266/examples/BlinkPolledTimeout/BlinkPolledTimeout.ino).
|
||||||
- Port over to ESP-IDF. The Arduino SDK is showing its limitations
|
- Port over to ESP-IDF. The Arduino SDK is showing its limitations
|
||||||
|
|
||||||
|
### **Features to add**
|
||||||
|
|
||||||
|
- Multi-language. German, Dutch, French
|
||||||
|
- Click on a device in the Web UI shows it's details
|
||||||
|
- Publish time can be customized per device (solar, mixing etc)
|
||||||
|
|
||||||
### **Customizing the Web UI**
|
### **Customizing the Web UI**
|
||||||
|
|
||||||
The Web is based off Rick's awesome [esp8266-react](https://github.com/rjwats/esp8266-react/) framework. These are the files that are modified:
|
The Web is based off Rick's awesome [esp8266-react](https://github.com/rjwats/esp8266-react/) framework. These are the files that are modified:
|
||||||
|
|
||||||
**`interface:`**
|
**`interface:`**
|
||||||
* `.env` (project name and project path to ems-esp)
|
* `.env` project name and project path to ems-esp
|
||||||
* `.env.development` (CORS URL)
|
* `.env.development` CORS URL
|
||||||
|
|
||||||
**`interface/public:`**
|
**`interface/public:`**
|
||||||
* `app/manifest.json` (ems-esp name)
|
* `app/manifest.json` ems-esp name
|
||||||
* `index.html` (ems-esp name)
|
* `index.html` ems-esp name
|
||||||
* `app/icon.png` (256x256 PNG)
|
* `app/icon.png` 256x256 PNG
|
||||||
* `favicon.ico`
|
* `favicon.ico` replaced
|
||||||
|
|
||||||
**`interface/src:`**
|
**`interface/src:`**
|
||||||
* `CustomMuiTheme.tsx` (colors for dark mode)
|
* `CustomMuiTheme.tsx` colors for dark mode
|
||||||
* `interface/src/wifi/WifiSettingsController.tsx` (rename esp8266-react)
|
* `interface/src/wifi/WifiSettingsController.tsx` rename esp8266-react
|
||||||
|
|
||||||
**`interface/src/project:`**
|
**`interface/src/project:`**
|
||||||
* `ProjectRouting.tsx` (removed demo, renamed DemoProject to EMSESP)
|
* `ProjectRouting.tsx` removed demo, added paths to ems-esp/status, ems-esp/settings and *
|
||||||
* `DemoProject.tsx` (remove /demo/ and changed title, renamed to EMSESP.tsx)
|
* `DemoProject.tsx` remove /demo/ and changed title, renamed to EMSESP.tsx
|
||||||
* `ProjectMenu.tsx` (title)
|
* `ProjectMenu.tsx` title change, added /ems-esp/settings
|
||||||
* `DemoInformation.tsx` (removed file)
|
* `DemoInformation.tsx` removed file
|
||||||
* `types.ts` (add variables)
|
* `types.ts` add variables
|
||||||
|
* added all custom files starting with EMSESP*
|
||||||
|
|
||||||
|
**`interface/src/mqtt:`**
|
||||||
|
* `types.ts` added mqtt_fails
|
||||||
|
* `MqttStatusForm.tsx` added MQTT Publish Errors
|
||||||
|
* `MqttStatus.ts` added function mqttPublishHighlight
|
||||||
|
* `MqttSettingsForm.tsx` added publish time, qos, format
|
||||||
|
|
||||||
|
**`interface/src/authentication:`**
|
||||||
|
* `AuthenticationWrapper.tsx` commented out features.security because we added version
|
||||||
|
* `AuthenticationContext.tsx` added version
|
||||||
|
* `MqttSettingsForm.tsx` added publish time, qos, format
|
||||||
|
|
||||||
|
**`interface/src/components:`**
|
||||||
|
* `MenuAppBar.tsx` added version to toolbar
|
||||||
|
|
||||||
|
**`interface/src/system:`**
|
||||||
|
* `types.ts` added uptime and free_mem
|
||||||
|
* `SystemStatusForm.tsx` added system uptime, % free mem
|
||||||
|
|
||||||
**`lib/framework`:**
|
**`lib/framework`:**
|
||||||
|
* `SystemStatus.h` added #include <LittleFS.h>, #include <uuid/log.h>, #include "../../src/system.h"
|
||||||
* `SystemStatus.h` : added #include <LittleFS.h>
|
* `SystemStatus.cpp` added LittleFS.info(fs_info); root["uptime"], root["free_mem"]
|
||||||
* `SystemStatus.cpp` : added LittleFS.info(fs_info);
|
* Commented out all `Serial.print`'s in all files
|
||||||
* Commented out all `Serial.print`'s
|
* `MqttStatus.h` added #include "../../src/mqtt.h"
|
||||||
* `features.ini`: -D FT_NTP=0
|
* `MqttStatus.cpp` added root["mqtt_fails"]
|
||||||
* customized `platformio.ini`
|
* `SecuritySettingsService.cpp` added version to the JWT payload
|
||||||
* customized `factory_settings.ini` with `ems-esp-neo` as password and `ems-esp` everywhere else
|
* `SecuritySettingsService.h` #include "../../src/version.h"
|
||||||
|
* `features.ini`: -D FT_NTP=0
|
||||||
|
* `platformio.ini` using our own version
|
||||||
|
* `factory_settings.ini` modified with `ems-esp-neo` as password and `ems-esp` everywhere else
|
||||||
|
|
||||||
|
|
||||||
Info on UI customizations:
|
UI customization links:
|
||||||
|
|
||||||
* icons: https://material-ui.com/components/material-icons/
|
* icons: https://material-ui.com/components/material-icons/
|
||||||
* colors: https://material-ui.com/customization/color/
|
* colors: https://material-ui.com/customization/color/
|
||||||
* tables: https://material-ui.com/components/tables/#dense-table
|
* tables: https://material-ui.com/components/tables/#dense-table
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import * as React from "react";
|
|||||||
export interface Me {
|
export interface Me {
|
||||||
username: string;
|
username: string;
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
|
version: string; // proddy added
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthenticationContext {
|
export interface AuthenticationContext {
|
||||||
|
|||||||
@@ -59,10 +59,11 @@ class AuthenticationWrapper extends React.Component<AuthenticationWrapperProps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh = () => {
|
refresh = () => {
|
||||||
if (!this.props.features.security) {
|
// proddy removed
|
||||||
this.setState({ initialized: true, context: { ...this.state.context, me: { admin: true, username: "admin" } } });
|
// if (!this.props.features.security) {
|
||||||
return;
|
// this.setState({ initialized: true, context: { ...this.state.context, me: { admin: true, username: "admin" } } });
|
||||||
}
|
// return;
|
||||||
|
// }
|
||||||
const accessToken = getStorage().getItem(ACCESS_TOKEN)
|
const accessToken = getStorage().getItem(ACCESS_TOKEN)
|
||||||
if (accessToken) {
|
if (accessToken) {
|
||||||
authorizedFetch(VERIFY_AUTHORIZATION_ENDPOINT)
|
authorizedFetch(VERIFY_AUTHORIZATION_ENDPOINT)
|
||||||
|
|||||||
@@ -124,11 +124,18 @@ class MenuAppBar extends React.Component<MenuAppBarProps, MenuAppBarState> {
|
|||||||
<Box display="flex">
|
<Box display="flex">
|
||||||
<img src="/app/icon.png" className={classes.toolbarImage} alt={PROJECT_NAME} />
|
<img src="/app/icon.png" className={classes.toolbarImage} alt={PROJECT_NAME} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Typography variant="h6" color="textPrimary">
|
<Typography variant="h6" color="textPrimary">
|
||||||
{PROJECT_NAME}
|
{PROJECT_NAME}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<Typography align="right" variant="caption" color="textPrimary">
|
||||||
|
{authenticatedContext.me.version}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<Divider absolute />
|
<Divider absolute />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
{features.project && (
|
{features.project && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<ProjectMenu />
|
<ProjectMenu />
|
||||||
@@ -149,12 +156,12 @@ class MenuAppBar extends React.Component<MenuAppBarProps, MenuAppBarState> {
|
|||||||
<ListItemText primary="Access Point" />
|
<ListItemText primary="Access Point" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{features.ntp && (
|
{features.ntp && (
|
||||||
<ListItem to='/ntp/' selected={path.startsWith('/ntp/')} button component={Link}>
|
<ListItem to='/ntp/' selected={path.startsWith('/ntp/')} button component={Link}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<AccessTimeIcon />
|
<AccessTimeIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Network Time" />
|
<ListItemText primary="Network Time" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
{features.mqtt && (
|
{features.mqtt && (
|
||||||
<ListItem to='/mqtt/' selected={path.startsWith('/mqtt/')} button component={Link}>
|
<ListItem to='/mqtt/' selected={path.startsWith('/mqtt/')} button component={Link}>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mqttStatusHighlight2 = ({ mqtt_fails }: MqttStatus, theme: Theme) => {
|
export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) => {
|
||||||
|
|
||||||
if (mqtt_fails === 0)
|
if (mqtt_fails === 0)
|
||||||
return theme.palette.success.main;
|
return theme.palette.success.main;
|
||||||
@@ -53,5 +53,4 @@ export const mqttStatusHighlight2 = ({ mqtt_fails }: MqttStatus, theme: Theme) =
|
|||||||
return theme.palette.warning.main;
|
return theme.palette.warning.main;
|
||||||
|
|
||||||
return theme.palette.success.main;
|
return theme.palette.success.main;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ import ReportIcon from '@material-ui/icons/Report';
|
|||||||
import SpeakerNotesOffIcon from "@material-ui/icons/SpeakerNotesOff";
|
import SpeakerNotesOffIcon from "@material-ui/icons/SpeakerNotesOff";
|
||||||
|
|
||||||
import { RestFormProps, FormActions, FormButton, HighlightAvatar } from '../components';
|
import { RestFormProps, FormActions, FormButton, HighlightAvatar } from '../components';
|
||||||
import { mqttStatusHighlight, mqttStatus, mqttStatusHighlight2, disconnectReason } from './MqttStatus';
|
import { mqttStatusHighlight, mqttStatus, mqttPublishHighlight, disconnectReason } from './MqttStatus';
|
||||||
import { MqttStatus } from './types';
|
import { MqttStatus } from './types';
|
||||||
|
|
||||||
type MqttStatusFormProps = RestFormProps<MqttStatus> & WithTheme;
|
type MqttStatusFormProps = RestFormProps<MqttStatus> & WithTheme;
|
||||||
@@ -30,7 +30,7 @@ class MqttStatusForm extends Component<MqttStatusFormProps> {
|
|||||||
<Divider variant="inset" component="li" />
|
<Divider variant="inset" component="li" />
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<HighlightAvatar color={mqttStatusHighlight2(data, theme)}>
|
<HighlightAvatar color={mqttPublishHighlight(data, theme)}>
|
||||||
<SpeakerNotesOffIcon />
|
<SpeakerNotesOffIcon />
|
||||||
</HighlightAvatar>
|
</HighlightAvatar>
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { AuthenticatedRoute } from '../authentication';
|
|||||||
|
|
||||||
import EMSESPStatusController from './EMSESPStatusController';
|
import EMSESPStatusController from './EMSESPStatusController';
|
||||||
import EMSESPDevicesController from './EMSESPDevicesController';
|
import EMSESPDevicesController from './EMSESPDevicesController';
|
||||||
|
import EMSESPHelp from './EMSESPHelp';
|
||||||
|
|
||||||
class EMSESP extends Component<RouteComponentProps> {
|
class EMSESP extends Component<RouteComponentProps> {
|
||||||
|
|
||||||
@@ -20,10 +21,12 @@ class EMSESP extends Component<RouteComponentProps> {
|
|||||||
return (
|
return (
|
||||||
<MenuAppBar sectionTitle="Dashboard">
|
<MenuAppBar sectionTitle="Dashboard">
|
||||||
<Tabs value={this.props.match.url} onChange={this.handleTabChange} variant="fullWidth">
|
<Tabs value={this.props.match.url} onChange={this.handleTabChange} variant="fullWidth">
|
||||||
<Tab value={`/${PROJECT_PATH}/status`} label="EMS-ESP Status" />
|
<Tab value={`/${PROJECT_PATH}/status`} label="EMS Status" />
|
||||||
<Tab value={`/${PROJECT_PATH}/devices`} label="EMS Devices" />
|
<Tab value={`/${PROJECT_PATH}/devices`} label="EMS Devices" />
|
||||||
|
<Tab value={`/${PROJECT_PATH}/help`} label="EMS-ESP Help" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/help`} component={EMSESPHelp} />
|
||||||
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/status`} component={EMSESPStatusController} />
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/status`} component={EMSESPStatusController} />
|
||||||
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/devices`} component={EMSESPDevicesController} />
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/devices`} component={EMSESPDevicesController} />
|
||||||
<Redirect to={`/${PROJECT_PATH}/status`} />
|
<Redirect to={`/${PROJECT_PATH}/status`} />
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
|
|||||||
(
|
(
|
||||||
<Box bgcolor="error.main" color="error.contrastText" p={2} mt={2} mb={2}>
|
<Box bgcolor="error.main" color="error.contrastText" p={2} mt={2} mb={2}>
|
||||||
<Typography variant="body1">
|
<Typography variant="body1">
|
||||||
No EMS devices found. Check connection and for Tx errors. Try forcing a scan.
|
No EMS devices found. Check the connection and for possible Tx errors and try scanning for new devices.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
@@ -174,8 +174,9 @@ class EMSESPDevicesForm extends Component<EMSESPDevicesFormProps, EMSESPDevicesF
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
<br></br>
|
||||||
{this.createTableItems()}
|
{this.createTableItems()}
|
||||||
|
<br></br>
|
||||||
<Box display="flex" flexWrap="wrap">
|
<Box display="flex" flexWrap="wrap">
|
||||||
<Box flexGrow={1} padding={1}>
|
<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}>
|
||||||
|
|||||||
35
interface/src/project/EMSESPHelp.tsx
Normal file
35
interface/src/project/EMSESPHelp.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Typography, Box, Link } from '@material-ui/core';
|
||||||
|
import { SectionContent } from '../components';
|
||||||
|
|
||||||
|
class EMSESPHelp extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<SectionContent title='EMS-ESP Help' titleGutter>
|
||||||
|
|
||||||
|
<Box bgcolor="info.main" border={1} p={3} mt={1} mb={0}>
|
||||||
|
<Typography variant="body1">
|
||||||
|
EMS-ESP is an open-source firmware to communicate with heating devices that support the EMS protocol, such as equipment from Bosch, Junkers, Nefit, Buderus and Worcester.
|
||||||
|
<p></p>
|
||||||
|
Please consider supporting this project via the GitHub page <Link href="https://github.com/proddy/EMS-ESP" color="primary">{'http://github.com/proddy/EMS-ESP'}</Link>.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<br></br>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
Check for news and updates on the <Link href="https://emsesp.github.io/docs/#/" color="primary">{'Wiki'}</Link>.
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
For live community chat go to <Link href="https://gitter.im/EMS-ESP/community#" color="primary">{'Gitter'}</Link>.
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
To report an issue or feature request go to <Link href="https://github.com/proddy/EMS-ESP/issues/new/choose" color="primary">{'the github project page'}</Link>.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
</SectionContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EMSESPHelp;
|
||||||
@@ -17,7 +17,7 @@ class EMSESPStatusController extends Component<EMSESPStatusControllerProps> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SectionContent title="EMS-ESP Status">
|
<SectionContent title="EMS Status">
|
||||||
<RestFormLoader
|
<RestFormLoader
|
||||||
{...this.props}
|
{...this.props}
|
||||||
render={formProps => <EMSESPStatusForm {...formProps} />}
|
render={formProps => <EMSESPStatusForm {...formProps} />}
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ import {
|
|||||||
ListItem,
|
ListItem,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Typography,
|
|
||||||
Box,
|
|
||||||
Link
|
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
|
||||||
import RefreshIcon from "@material-ui/icons/Refresh";
|
import RefreshIcon from "@material-ui/icons/Refresh";
|
||||||
@@ -42,17 +39,7 @@ class EMSESPStatusForm extends Component<EMSESPStatusFormProps> {
|
|||||||
const { data, theme } = this.props;
|
const { data, theme } = this.props;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Box bgcolor="info.main" border={1} p={3} mt={1} mb={0}>
|
|
||||||
<Typography variant="body1">
|
|
||||||
Firmware Version is <b>{data.version}</b>
|
|
||||||
<br /><br />
|
|
||||||
Check for news and updates on the <Link href="https://emsesp.github.io/docs/#/" color="primary">{'Wiki'}</Link>
|
|
||||||
<br/>
|
|
||||||
For live community chat go to <Link href="https://gitter.im/EMS-ESP/community#" color="primary">{'Gitter'}</Link>
|
|
||||||
<br/>
|
|
||||||
To report issues, contribute and give kudos visit <Link href="https://github.com/proddy/EMS-ESP" color="primary">{'github.com/proddy/EMS-ESP'}</Link>
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<HighlightAvatar color={busStatusHighlight(data, theme)}>
|
<HighlightAvatar color={busStatusHighlight(data, theme)}>
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export enum busConnectionStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EMSESPStatus {
|
export interface EMSESPStatus {
|
||||||
version: string;
|
|
||||||
status: busConnectionStatus;
|
status: busConnectionStatus;
|
||||||
rx_received: number;
|
rx_received: number;
|
||||||
tx_sent: number;
|
tx_sent: number;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import {restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
|
import { restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
|
||||||
import WiFiSettingsForm from './WiFiSettingsForm';
|
import WiFiSettingsForm from './WiFiSettingsForm';
|
||||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
|
||||||
import { WIFI_SETTINGS_ENDPOINT } from '../api';
|
import { WIFI_SETTINGS_ENDPOINT } from '../api';
|
||||||
import { WiFiSettings } from './types';
|
import { WiFiSettings } from './types';
|
||||||
|
|
||||||
@@ -10,39 +9,15 @@ type WiFiSettingsControllerProps = RestControllerProps<WiFiSettings>;
|
|||||||
|
|
||||||
class WiFiSettingsController extends Component<WiFiSettingsControllerProps> {
|
class WiFiSettingsController extends Component<WiFiSettingsControllerProps> {
|
||||||
|
|
||||||
static contextType = WiFiConnectionContext;
|
|
||||||
context!: React.ContextType<typeof WiFiConnectionContext>;
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { selectedNetwork } = this.context;
|
|
||||||
if (selectedNetwork) {
|
|
||||||
const wifiSettings: WiFiSettings = {
|
|
||||||
ssid: selectedNetwork.ssid,
|
|
||||||
password: "",
|
|
||||||
hostname: "ems-esp",
|
|
||||||
static_ip_config: false,
|
|
||||||
}
|
|
||||||
this.props.setData(wifiSettings);
|
|
||||||
} else {
|
|
||||||
this.props.loadData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deselectNetworkAndLoadData = () => {
|
|
||||||
this.context.deselectNetwork();
|
|
||||||
this.props.loadData();
|
this.props.loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.context.deselectNetwork();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SectionContent title="WiFi Settings">
|
<SectionContent title="WiFi Settings">
|
||||||
<RestFormLoader
|
<RestFormLoader
|
||||||
{...this.props}
|
{...this.props}
|
||||||
loadData={this.deselectNetworkAndLoadData}
|
|
||||||
render={formProps => <WiFiSettingsForm {...formProps} />}
|
render={formProps => <WiFiSettingsForm {...formProps} />}
|
||||||
/>
|
/>
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
@@ -51,4 +26,4 @@ class WiFiSettingsController extends Component<WiFiSettingsControllerProps> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default restController(WIFI_SETTINGS_ENDPOINT, WiFiSettingsController);
|
export default restController(WIFI_SETTINGS_ENDPOINT, WiFiSettingsController);
|
||||||
@@ -24,15 +24,39 @@ class WiFiSettingsForm extends React.Component<WiFiStatusFormProps> {
|
|||||||
static contextType = WiFiConnectionContext;
|
static contextType = WiFiConnectionContext;
|
||||||
context!: React.ContextType<typeof WiFiConnectionContext>;
|
context!: React.ContextType<typeof WiFiConnectionContext>;
|
||||||
|
|
||||||
|
constructor(props: WiFiStatusFormProps, context: WiFiConnectionContext) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
const { selectedNetwork } = context;
|
||||||
|
if (selectedNetwork) {
|
||||||
|
const wifiSettings: WiFiSettings = {
|
||||||
|
ssid: selectedNetwork.ssid,
|
||||||
|
password: "",
|
||||||
|
hostname: props.data.hostname,
|
||||||
|
static_ip_config: false,
|
||||||
|
}
|
||||||
|
props.setData(wifiSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
ValidatorForm.addValidationRule('isIP', isIP);
|
ValidatorForm.addValidationRule('isIP', isIP);
|
||||||
ValidatorForm.addValidationRule('isHostname', isHostname);
|
ValidatorForm.addValidationRule('isHostname', isHostname);
|
||||||
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP));
|
ValidatorForm.addValidationRule('isOptionalIP', optional(isIP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deselectNetworkAndLoadData = () => {
|
||||||
|
this.context.deselectNetwork();
|
||||||
|
this.props.loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.context.deselectNetwork();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { selectedNetwork, deselectNetwork } = this.context;
|
const { selectedNetwork, deselectNetwork } = this.context;
|
||||||
const { data, handleValueChange, saveData, loadData } = this.props;
|
const { data, handleValueChange, saveData } = this.props;
|
||||||
return (
|
return (
|
||||||
<ValidatorForm onSubmit={saveData} ref="WiFiSettingsForm">
|
<ValidatorForm onSubmit={saveData} ref="WiFiSettingsForm">
|
||||||
{
|
{
|
||||||
@@ -167,7 +191,7 @@ class WiFiSettingsForm extends React.Component<WiFiStatusFormProps> {
|
|||||||
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
|
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
|
||||||
Save
|
Save
|
||||||
</FormButton>
|
</FormButton>
|
||||||
<FormButton variant="contained" color="secondary" onClick={loadData}>
|
<FormButton variant="contained" color="secondary" onClick={this.deselectNetworkAndLoadData}>
|
||||||
Reset
|
Reset
|
||||||
</FormButton>
|
</FormButton>
|
||||||
</FormActions>
|
</FormActions>
|
||||||
@@ -176,4 +200,4 @@ class WiFiSettingsForm extends React.Component<WiFiStatusFormProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WiFiSettingsForm;
|
export default WiFiSettingsForm;
|
||||||
@@ -16,7 +16,7 @@ void MqttStatus::mqttStatus(AsyncWebServerRequest * request) {
|
|||||||
root["client_id"] = _mqttSettingsService->getClientId();
|
root["client_id"] = _mqttSettingsService->getClientId();
|
||||||
root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason();
|
root["disconnect_reason"] = (uint8_t)_mqttSettingsService->getDisconnectReason();
|
||||||
|
|
||||||
root["mqtt_fails"] = emsesp::Mqtt::publish_fails();
|
root["mqtt_fails"] = emsesp::Mqtt::publish_fails(); // proddy added
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../src/mqtt.h"
|
#include "../../src/mqtt.h" // proddy added
|
||||||
|
|
||||||
#include <MqttSettingsService.h>
|
#include <MqttSettingsService.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ Authentication SecuritySettingsService::authenticate(const String& username, con
|
|||||||
inline void populateJWTPayload(JsonObject& payload, User* user) {
|
inline void populateJWTPayload(JsonObject& payload, User* user) {
|
||||||
payload["username"] = user->username;
|
payload["username"] = user->username;
|
||||||
payload["admin"] = user->admin;
|
payload["admin"] = user->admin;
|
||||||
|
payload["version"] = EMSESP_APP_VERSION; // proddy added
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) {
|
boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <HttpEndpoint.h>
|
#include <HttpEndpoint.h>
|
||||||
#include <FSPersistence.h>
|
#include <FSPersistence.h>
|
||||||
|
|
||||||
|
#include "../../src/version.h" // added by proddy
|
||||||
|
|
||||||
#ifndef FACTORY_ADMIN_USERNAME
|
#ifndef FACTORY_ADMIN_USERNAME
|
||||||
#define FACTORY_ADMIN_USERNAME "admin"
|
#define FACTORY_ADMIN_USERNAME "admin"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ void SystemStatus::systemStatus(AsyncWebServerRequest * request) {
|
|||||||
root["fs_used"] = SPIFFS.usedBytes();
|
root["fs_used"] = SPIFFS.usedBytes();
|
||||||
#elif defined(ESP8266)
|
#elif defined(ESP8266)
|
||||||
FSInfo fs_info;
|
FSInfo fs_info;
|
||||||
LittleFS.info(fs_info); // TODO added littlefs
|
LittleFS.info(fs_info); // // proddy added
|
||||||
root["fs_total"] = fs_info.totalBytes;
|
root["fs_total"] = fs_info.totalBytes;
|
||||||
root["fs_used"] = fs_info.usedBytes;
|
root["fs_used"] = fs_info.usedBytes;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3); // proddy added
|
||||||
root["free_mem"] = emsesp::System::free_mem();
|
root["free_mem"] = emsesp::System::free_mem(); // proddy added
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <ESPAsyncTCP.h>
|
#include <ESPAsyncTCP.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <LittleFS.h> // TODO added littlefs
|
#include <LittleFS.h> // proddy added
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|
||||||
#include <uuid/log.h>
|
#include <uuid/log.h> // proddy added
|
||||||
#include "../../src/system.h"
|
#include "../../src/system.h" // proddy added
|
||||||
|
|
||||||
#define MAX_ESP_STATUS_SIZE 1024
|
#define MAX_ESP_STATUS_SIZE 1024
|
||||||
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
||||||
|
|||||||
BIN
media/web_devices.PNG
Normal file
BIN
media/web_devices.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
media/web_mqtt.PNG
Normal file
BIN
media/web_mqtt.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 39 KiB |
@@ -37,7 +37,7 @@ libs_core =
|
|||||||
|
|
||||||
[env]
|
[env]
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:scripts/build_interface.py
|
; pre:scripts/build_interface.py
|
||||||
scripts/main_script.py
|
scripts/main_script.py
|
||||||
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ void EMSESPStatusService::emsespStatusService(AsyncWebServerRequest * request) {
|
|||||||
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_EMSESP_STATUS_SIZE);
|
AsyncJsonResponse * response = new AsyncJsonResponse(false, MAX_EMSESP_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
root["version"] = EMSESP_APP_VERSION;
|
|
||||||
|
|
||||||
root["status"] = EMSESP::bus_status(); // 0, 1 or 2
|
root["status"] = EMSESP::bus_status(); // 0, 1 or 2
|
||||||
root["rx_received"] = EMSESP::rxservice_.telegram_count();
|
root["rx_received"] = EMSESP::rxservice_.telegram_count();
|
||||||
root["tx_sent"] = EMSESP::txservice_.telegram_read_count() + EMSESP::txservice_.telegram_write_count();
|
root["tx_sent"] = EMSESP::txservice_.telegram_read_count() + EMSESP::txservice_.telegram_write_count();
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "2.0.0_b4" // based off a32
|
#define EMSESP_APP_VERSION "2.0.0_b4"
|
||||||
|
|||||||
Reference in New Issue
Block a user