mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Optimize WebUI rendering when using Dialog Boxes #1116
This commit is contained in:
@@ -212,7 +212,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102)
|
- Added pool data to telegrams 0x494 & 0x495 [#102](https://github.com/emsesp/EMS-ESP32/issues/102)
|
||||||
- Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108)
|
- Add RC300 second summermode telegram [#108](https://github.com/emsesp/EMS-ESP32/issues/108)
|
||||||
- Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
|
- Add support for the RC25 thermostat [#106](https://github.com/emsesp/EMS-ESP32/issues/106)
|
||||||
- Add new command 'entities' for a device, e.g. http://ems-esp/api/boiler/entities to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116)
|
- Add new command 'entities' for a device, e.g. <http://ems-esp/api/boiler/entities> to show the shortname, description and HA Entity name (if HA enabled) [#116](https://github.com/emsesp/EMS-ESP32/issues/116)
|
||||||
- Support for Junkers program and remote (fb10/fb110) temperature
|
- Support for Junkers program and remote (fb10/fb110) temperature
|
||||||
- Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129)
|
- Home Assistant `state_class` attribute for Wh, kWh, W and KW [#129](https://github.com/emsesp/EMS-ESP32/issues/129)
|
||||||
- Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136)
|
- Add current room influence for RC300 [#136](https://github.com/emsesp/EMS-ESP32/issues/136)
|
||||||
@@ -434,4 +434,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- some names of mqtt-tags like in v2.2.1
|
- some names of mqtt-tags like in v2.2.1
|
||||||
- new ESP32 partition side to allow for smoother OTA and fallback
|
- new ESP32 partition side to allow for smoother OTA and fallback
|
||||||
- Network Gateway IP is optional (#682)emsesp/EMS-ESP
|
- Network Gateway IP is optional (#682)emsesp/EMS-ESP
|
||||||
- moved to a new GitHub repo https://github.com/emsesp/EMS-ESP32
|
- moved to a new GitHub repo <https://github.com/emsesp/EMS-ESP32>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES**
|
## **IMPORTANT! BREAKING CHANGES**
|
||||||
|
|
||||||
|
- dallassensor has been renamed to temperaturesensor in MQTT payloads
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Workaround for better Domoticz MQTT intergration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904)
|
- Workaround for better Domoticz MQTT intergration? [#904](https://github.com/emsesp/EMS-ESP32/issues/904)
|
||||||
@@ -29,3 +31,5 @@
|
|||||||
- Improved HA Discovery so previous configs no longer need to be removed when starting [#1077](https://github.com/emsesp/EMS-ESP32/pull/1077) (thanks @pswid!)
|
- Improved HA Discovery so previous configs no longer need to be removed when starting [#1077](https://github.com/emsesp/EMS-ESP32/pull/1077) (thanks @pswid!)
|
||||||
- Enlarge UART-Stack to 2,5k
|
- Enlarge UART-Stack to 2,5k
|
||||||
- Retry timeout for Mqtt-QOS1/2 10seconds
|
- Retry timeout for Mqtt-QOS1/2 10seconds
|
||||||
|
- Optimize WebUI rendering when using Dialog Boxes [#1116](https://github.com/emsesp/EMS-ESP32/issues/1116)
|
||||||
|
- Optimize Web libraries to reduce bundle size (3.6.x) [#1112](https://github.com/emsesp/EMS-ESP32/issues/1112)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
"@typescript-eslint/no-implied-eval": "off",
|
"@typescript-eslint/no-implied-eval": "off",
|
||||||
"@typescript-eslint/no-misused-promises": "off",
|
"@typescript-eslint/no-misused-promises": "off",
|
||||||
"arrow-body-style": ["error", "as-needed"],
|
"arrow-body-style": ["error", "as-needed"],
|
||||||
"react-hooks/exhaustive-deps": "error",
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
"@typescript-eslint/consistent-type-imports": [
|
"@typescript-eslint/consistent-type-imports": [
|
||||||
"error",
|
"error",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,20 +20,20 @@
|
|||||||
"lint-fixall": "eslint . --cache --fix"
|
"lint-fixall": "eslint . --cache --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.8",
|
||||||
"@emotion/styled": "^11.10.6",
|
"@emotion/styled": "^11.10.8",
|
||||||
"@msgpack/msgpack": "^3.0.0-beta2",
|
"@msgpack/msgpack": "^3.0.0-beta2",
|
||||||
"@mui/icons-material": "^5.11.16",
|
"@mui/icons-material": "^5.11.16",
|
||||||
"@mui/material": "^5.12.1",
|
"@mui/material": "^5.12.2",
|
||||||
"@remix-run/router": "^1.5.0",
|
"@remix-run/router": "^1.5.0",
|
||||||
"@table-library/react-table-library": "4.1.0",
|
"@table-library/react-table-library": "4.1.2",
|
||||||
"@types/lodash-es": "^4.17.7",
|
"@types/lodash-es": "^4.17.7",
|
||||||
"@types/node": "^18.16.0",
|
"@types/node": "^18.16.2",
|
||||||
"@types/react": "^18.0.38",
|
"@types/react": "^18.2.0",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.2.1",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"axios": "^1.3.6",
|
"axios": "^1.4.0",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"rollup-plugin-visualizer": "^5.9.0",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
"terser": "^5.17.1",
|
"terser": "^5.17.1",
|
||||||
"vite": "^4.3.1",
|
"vite": "^4.3.3",
|
||||||
"vite-plugin-svgr": "^2.4.0",
|
"vite-plugin-svgr": "^2.4.0",
|
||||||
"vite-tsconfig-paths": "^4.2.0"
|
"vite-tsconfig-paths": "^4.2.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment } from '@mui/material';
|
import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment, TextField } from '@mui/material';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import type { ValidateFieldsError } from 'async-validator';
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
@@ -94,7 +94,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="client_id"
|
name="client_id"
|
||||||
label={LL.ID_OF(LL.CLIENT()) + ' (' + LL.OPTIONAL() + ')'}
|
label={LL.ID_OF(LL.CLIENT()) + ' (' + LL.OPTIONAL() + ')'}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -105,7 +105,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="username"
|
name="username"
|
||||||
label={LL.USERNAME(0)}
|
label={LL.USERNAME(0)}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -143,7 +143,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="mqtt_qos"
|
name="mqtt_qos"
|
||||||
label="QoS"
|
label="QoS"
|
||||||
value={data.mqtt_qos}
|
value={data.mqtt_qos}
|
||||||
@@ -156,7 +156,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<MenuItem value={0}>0</MenuItem>
|
<MenuItem value={0}>0</MenuItem>
|
||||||
<MenuItem value={1}>1</MenuItem>
|
<MenuItem value={1}>1</MenuItem>
|
||||||
<MenuItem value={2}>2</MenuItem>
|
<MenuItem value={2}>2</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -171,7 +171,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.FORMATTING()}
|
{LL.FORMATTING()}
|
||||||
</Typography>
|
</Typography>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="nested_format"
|
name="nested_format"
|
||||||
label={LL.MQTT_FORMAT()}
|
label={LL.MQTT_FORMAT()}
|
||||||
value={data.nested_format}
|
value={data.nested_format}
|
||||||
@@ -183,7 +183,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
>
|
>
|
||||||
<MenuItem value={1}>{LL.MQTT_NEST_1()}</MenuItem>
|
<MenuItem value={1}>{LL.MQTT_NEST_1()}</MenuItem>
|
||||||
<MenuItem value={2}>{LL.MQTT_NEST_2()}</MenuItem>
|
<MenuItem value={2}>{LL.MQTT_NEST_2()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
control={<Checkbox name="send_response" checked={data.send_response} onChange={updateFormValue} />}
|
||||||
label={LL.MQTT_RESPONSE()}
|
label={LL.MQTT_RESPONSE()}
|
||||||
@@ -233,7 +233,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
alignItems="flex-start"
|
alignItems="flex-start"
|
||||||
>
|
>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="discovery_type"
|
name="discovery_type"
|
||||||
label={LL.MQTT_PUBLISH_TEXT_5()}
|
label={LL.MQTT_PUBLISH_TEXT_5()}
|
||||||
value={data.discovery_type}
|
value={data.discovery_type}
|
||||||
@@ -245,10 +245,10 @@ const MqttSettingsForm: FC = () => {
|
|||||||
>
|
>
|
||||||
<MenuItem value={0}>Home Assistant</MenuItem>
|
<MenuItem value={0}>Home Assistant</MenuItem>
|
||||||
<MenuItem value={1}>Domoticz</MenuItem>
|
<MenuItem value={1}>Domoticz</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="discovery_prefix"
|
name="discovery_prefix"
|
||||||
label={LL.MQTT_PUBLISH_TEXT_4()}
|
label={LL.MQTT_PUBLISH_TEXT_4()}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -259,7 +259,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="entity_format"
|
name="entity_format"
|
||||||
label={LL.MQTT_ENTITY_FORMAT()}
|
label={LL.MQTT_ENTITY_FORMAT()}
|
||||||
value={data.entity_format}
|
value={data.entity_format}
|
||||||
@@ -272,7 +272,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
<MenuItem value={0}>{LL.MQTT_ENTITY_FORMAT_0()}</MenuItem>
|
||||||
<MenuItem value={1}>{LL.MQTT_ENTITY_FORMAT_1()}</MenuItem>
|
<MenuItem value={1}>{LL.MQTT_ENTITY_FORMAT_1()}</MenuItem>
|
||||||
<MenuItem value={2}>{LL.MQTT_ENTITY_FORMAT_2()}</MenuItem>
|
<MenuItem value={2}>{LL.MQTT_ENTITY_FORMAT_2()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
@@ -299,8 +299,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_boiler"
|
name="publish_time_boiler"
|
||||||
label={LL.MQTT_INT_BOILER()}
|
label={LL.MQTT_INT_BOILER()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -315,8 +314,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_thermostat"
|
name="publish_time_thermostat"
|
||||||
label={LL.MQTT_INT_THERMOSTATS()}
|
label={LL.MQTT_INT_THERMOSTATS()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -331,8 +329,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_solar"
|
name="publish_time_solar"
|
||||||
label={LL.MQTT_INT_SOLAR()}
|
label={LL.MQTT_INT_SOLAR()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -347,8 +344,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_mixer"
|
name="publish_time_mixer"
|
||||||
label={LL.MQTT_INT_MIXER()}
|
label={LL.MQTT_INT_MIXER()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -363,8 +359,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_sensor"
|
name="publish_time_sensor"
|
||||||
label={LL.TEMP_SENSORS()}
|
label={LL.TEMP_SENSORS()}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@@ -379,8 +374,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="publish_time_other"
|
name="publish_time_other"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
|
endAdornment: <InputAdornment position="end">{LL.SECONDS()}</InputAdornment>
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import {
|
|||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Typography,
|
Typography,
|
||||||
InputAdornment
|
InputAdornment,
|
||||||
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useContext, useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@@ -165,7 +166,6 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="tx_power"
|
name="tx_power"
|
||||||
@@ -180,21 +180,17 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
type="number"
|
type="number"
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />}
|
control={<Checkbox name="nosleep" checked={data.nosleep} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_DISABLE_SLEEP()}
|
label={LL.NETWORK_DISABLE_SLEEP()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="bandwidth20" checked={data.bandwidth20} onChange={updateFormValue} />}
|
control={<Checkbox name="bandwidth20" checked={data.bandwidth20} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_LOW_BAND()}
|
label={LL.NETWORK_LOW_BAND()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.GENERAL_OPTIONS()}
|
{LL.GENERAL_OPTIONS()}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="hostname"
|
name="hostname"
|
||||||
@@ -205,19 +201,16 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="enableMDNS" checked={data.enableMDNS} onChange={updateFormValue} />}
|
control={<Checkbox name="enableMDNS" checked={data.enableMDNS} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_USE_DNS()}
|
label={LL.NETWORK_USE_DNS()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="enableCORS" checked={data.enableCORS} onChange={updateFormValue} />}
|
control={<Checkbox name="enableCORS" checked={data.enableCORS} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_ENABLE_CORS()}
|
label={LL.NETWORK_ENABLE_CORS()}
|
||||||
/>
|
/>
|
||||||
{data.enableCORS && (
|
{data.enableCORS && (
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
fieldErrors={fieldErrors}
|
|
||||||
name="CORSOrigin"
|
name="CORSOrigin"
|
||||||
label={LL.NETWORK_CORS_ORIGIN()}
|
label={LL.NETWORK_CORS_ORIGIN()}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -227,12 +220,10 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />}
|
control={<Checkbox name="enableIPv6" checked={data.enableIPv6} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_ENABLE_IPV6()}
|
label={LL.NETWORK_ENABLE_IPV6()}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />}
|
control={<Checkbox name="static_ip_config" checked={data.static_ip_config} onChange={updateFormValue} />}
|
||||||
label={LL.NETWORK_FIXED_IP()}
|
label={LL.NETWORK_FIXED_IP()}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { Box, styled, Button, Checkbox, MenuItem, Grid } from '@mui/material';
|
import { Box, styled, Button, Checkbox, MenuItem, Grid, TextField } from '@mui/material';
|
||||||
import { useState, useEffect, useCallback, useLayoutEffect } from 'react';
|
import { useState, useEffect, useCallback, useLayoutEffect } from 'react';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
@@ -138,7 +138,6 @@ const SystemLog: FC = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
es.close();
|
es.close();
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
@@ -150,7 +149,7 @@ const SystemLog: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Grid container spacing={3} direction="row" justifyContent="flex-start" alignItems="center">
|
<Grid container spacing={3} direction="row" justifyContent="flex-start" alignItems="center">
|
||||||
<Grid item xs={2}>
|
<Grid item xs={2}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="level"
|
name="level"
|
||||||
label={LL.LOG_LEVEL()}
|
label={LL.LOG_LEVEL()}
|
||||||
value={data.level}
|
value={data.level}
|
||||||
@@ -167,10 +166,10 @@ const SystemLog: FC = () => {
|
|||||||
<MenuItem value={6}>INFO</MenuItem>
|
<MenuItem value={6}>INFO</MenuItem>
|
||||||
<MenuItem value={7}>DEBUG</MenuItem>
|
<MenuItem value={7}>DEBUG</MenuItem>
|
||||||
<MenuItem value={9}>ALL</MenuItem>
|
<MenuItem value={9}>ALL</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={2}>
|
<Grid item xs={2}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="max_messages"
|
name="max_messages"
|
||||||
label={LL.BUFFER_SIZE()}
|
label={LL.BUFFER_SIZE()}
|
||||||
value={data.max_messages}
|
value={data.max_messages}
|
||||||
@@ -184,7 +183,7 @@ const SystemLog: FC = () => {
|
|||||||
<MenuItem value={50}>50</MenuItem>
|
<MenuItem value={50}>50</MenuItem>
|
||||||
<MenuItem value={75}>75</MenuItem>
|
<MenuItem value={75}>75</MenuItem>
|
||||||
<MenuItem value={100}>100</MenuItem>
|
<MenuItem value={100}>100</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const de: Translation = {
|
|||||||
ENTITY_NAME: 'Entitätsname',
|
ENTITY_NAME: 'Entitätsname',
|
||||||
VALUE: '{{Wert|wert}}',
|
VALUE: '{{Wert|wert}}',
|
||||||
SHOW_FAV: 'nur Favoriten anzeigen',
|
SHOW_FAV: 'nur Favoriten anzeigen',
|
||||||
DEVICE_SENSOR_DATA: 'Geräte- und Sensordaten',
|
DEVICE_DATA: 'Gerätedaten',
|
||||||
DEVICES_SENSORS: 'Geräte & Sensoren',
|
SENSOR_DATA: 'Sensordaten',
|
||||||
ATTACHED_SENSORS: 'Angeschlossene EMS-ESP Sensoren',
|
DEVICES: 'Geräte',
|
||||||
|
SENSORS: 'Sensoren',
|
||||||
RUN_COMMAND: 'Befehl ausführen',
|
RUN_COMMAND: 'Befehl ausführen',
|
||||||
CHANGE_VALUE: 'Wert ändern',
|
CHANGE_VALUE: 'Wert ändern',
|
||||||
CANCEL: 'Abbrechen',
|
CANCEL: 'Abbrechen',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const en: Translation = {
|
|||||||
ENTITY_NAME: 'Entity Name',
|
ENTITY_NAME: 'Entity Name',
|
||||||
VALUE: '{{Value|value}}',
|
VALUE: '{{Value|value}}',
|
||||||
SHOW_FAV: 'only show favorites',
|
SHOW_FAV: 'only show favorites',
|
||||||
DEVICE_SENSOR_DATA: 'Device and Sensor Data',
|
DEVICE_DATA: 'Device Data',
|
||||||
DEVICES_SENSORS: 'Devices & Sensors',
|
SENSOR_DATA: 'Sensor Data',
|
||||||
ATTACHED_SENSORS: 'Attached EMS-ESP Sensors',
|
DEVICES: 'Devices',
|
||||||
|
SENSORS: 'Sensors',
|
||||||
RUN_COMMAND: 'Call Command',
|
RUN_COMMAND: 'Call Command',
|
||||||
CHANGE_VALUE: 'Change Value',
|
CHANGE_VALUE: 'Change Value',
|
||||||
CANCEL: 'Cancel',
|
CANCEL: 'Cancel',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const fr: Translation = {
|
|||||||
ENTITY_NAME: 'Nom de l\'entité',
|
ENTITY_NAME: 'Nom de l\'entité',
|
||||||
VALUE: 'Valeur',
|
VALUE: 'Valeur',
|
||||||
SHOW_FAV: 'ne montrer que les favoris',
|
SHOW_FAV: 'ne montrer que les favoris',
|
||||||
DEVICE_SENSOR_DATA: 'Données des appareils et capteurs',
|
DEVICE_DATA: 'Données des appareils',
|
||||||
DEVICES_SENSORS: 'Appareils et capteurs',
|
SENSOR_DATA: 'Données des capteurs',
|
||||||
ATTACHED_SENSORS: 'Capteurs EMS-ESP connectés',
|
DEVICES: 'Appareils',
|
||||||
|
SENSORS: 'Capteurs',
|
||||||
RUN_COMMAND: 'Lancer une commande',
|
RUN_COMMAND: 'Lancer une commande',
|
||||||
CHANGE_VALUE: 'Changer la valeur',
|
CHANGE_VALUE: 'Changer la valeur',
|
||||||
CANCEL: 'Annuler',
|
CANCEL: 'Annuler',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const nl: Translation = {
|
|||||||
ENTITY_NAME: 'Entiteit',
|
ENTITY_NAME: 'Entiteit',
|
||||||
VALUE: '{{Waarde|waarde}}',
|
VALUE: '{{Waarde|waarde}}',
|
||||||
SHOW_FAV: 'alleen favorieten weergeven',
|
SHOW_FAV: 'alleen favorieten weergeven',
|
||||||
DEVICE_SENSOR_DATA: 'Apparaat en Sensor data',
|
SENSOR_DATA: 'Sensor data',
|
||||||
DEVICES_SENSORS: 'Apparaten & Sensoren',
|
DEVICE_DATA: 'Apparaat data',
|
||||||
ATTACHED_SENSORS: 'Aangesloten EMS-ESP sensoren',
|
DEVICES: 'Apparaten',
|
||||||
|
SENSORS: 'Sensoren',
|
||||||
RUN_COMMAND: 'Call commando',
|
RUN_COMMAND: 'Call commando',
|
||||||
CHANGE_VALUE: 'Wijzig waarde',
|
CHANGE_VALUE: 'Wijzig waarde',
|
||||||
CANCEL: 'Annuleren',
|
CANCEL: 'Annuleren',
|
||||||
@@ -136,7 +137,7 @@ const nl: Translation = {
|
|||||||
BOOLEAN_FORMAT_API: 'Boolean formaat API/MQTT',
|
BOOLEAN_FORMAT_API: 'Boolean formaat API/MQTT',
|
||||||
ENUM_FORMAT: 'Enum formaat API/MQTT',
|
ENUM_FORMAT: 'Enum formaat API/MQTT',
|
||||||
INDEX: 'Index',
|
INDEX: 'Index',
|
||||||
ENABLE_PARASITE: 'Activeer Dallas parasitaire modus',
|
ENABLE_PARASITE: 'Activeer parasitaire modus',
|
||||||
LOGGING: 'Logging',
|
LOGGING: 'Logging',
|
||||||
LOG_HEX: 'Log EMS telegrammen in hexadecimaal',
|
LOG_HEX: 'Log EMS telegrammen in hexadecimaal',
|
||||||
ENABLE_SYSLOG: 'Activeer Syslog',
|
ENABLE_SYSLOG: 'Activeer Syslog',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const no: Translation = {
|
|||||||
ENTITY_NAME: 'Objektsnavn',
|
ENTITY_NAME: 'Objektsnavn',
|
||||||
VALUE: '{{Verdi|verdi}}',
|
VALUE: '{{Verdi|verdi}}',
|
||||||
SHOW_FAV: ' Vis kun favoritter',
|
SHOW_FAV: ' Vis kun favoritter',
|
||||||
DEVICE_SENSOR_DATA: 'Enheter og Sensordata',
|
DEVICE_DATA: 'Enheterdata',
|
||||||
DEVICES_SENSORS: 'Enheter og Sensorer',
|
SENSOR_DATA: 'Sensordata',
|
||||||
ATTACHED_SENSORS: 'Tilkoblede EMS-ESP Sensorer',
|
DEVICES: 'Enheter',
|
||||||
|
SENSORS: 'Sensorer',
|
||||||
RUN_COMMAND: 'Kjør kommando',
|
RUN_COMMAND: 'Kjør kommando',
|
||||||
CHANGE_VALUE: 'Endre Verdi',
|
CHANGE_VALUE: 'Endre Verdi',
|
||||||
CANCEL: 'Avbryt',
|
CANCEL: 'Avbryt',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const pl: BaseTranslation = {
|
|||||||
ENTITY_NAME: 'Nazwa encji',
|
ENTITY_NAME: 'Nazwa encji',
|
||||||
VALUE: '{{W|w|}}artość',
|
VALUE: '{{W|w|}}artość',
|
||||||
SHOW_FAV: 'Pokaż tylko "ulubione"',
|
SHOW_FAV: 'Pokaż tylko "ulubione"',
|
||||||
DEVICE_SENSOR_DATA: 'Dane z urządzeń i czujników',
|
DEVICE_DATA: 'Dane z urządzeń',
|
||||||
DEVICES_SENSORS: 'Urządzenia i czujniki',
|
SENSOR_DATA: 'Dane z czujników',
|
||||||
ATTACHED_SENSORS: 'Urządzenia podłączone do EMS-ESP (czujniki temperatury/analogowe/cyfrowe, wyjścia cyfrowe)',
|
DEVICES: 'Urządzenia',
|
||||||
|
SENSORS: 'Czujniki',
|
||||||
RUN_COMMAND: 'Wykonaj komendę',
|
RUN_COMMAND: 'Wykonaj komendę',
|
||||||
CHANGE_VALUE: 'Zmień wartość',
|
CHANGE_VALUE: 'Zmień wartość',
|
||||||
CANCEL: 'Anuluj',
|
CANCEL: 'Anuluj',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const sv: Translation = {
|
|||||||
ENTITY_NAME: 'Entitetsnamn',
|
ENTITY_NAME: 'Entitetsnamn',
|
||||||
VALUE: '{{Värde|värde}}',
|
VALUE: '{{Värde|värde}}',
|
||||||
SHOW_FAV: 'Visa enbart favoriter',
|
SHOW_FAV: 'Visa enbart favoriter',
|
||||||
DEVICE_SENSOR_DATA: 'Enhets och Sensor-data',
|
DEVICE_DATA: 'Enhets data',
|
||||||
DEVICES_SENSORS: 'Enheter & Sensorer',
|
SENSOR_DATA: 'Sensor data',
|
||||||
ATTACHED_SENSORS: 'Anslutna EMS-ESP Sensorer',
|
DEVICES: 'Enheter',
|
||||||
|
SENSORS: 'Sensorer',
|
||||||
RUN_COMMAND: 'Kör Kommando',
|
RUN_COMMAND: 'Kör Kommando',
|
||||||
CHANGE_VALUE: 'Ändra Värde',
|
CHANGE_VALUE: 'Ändra Värde',
|
||||||
CANCEL: 'Avbryt',
|
CANCEL: 'Avbryt',
|
||||||
|
|||||||
@@ -38,9 +38,10 @@ const tr: Translation = {
|
|||||||
ENTITY_NAME: 'Valık Adı',
|
ENTITY_NAME: 'Valık Adı',
|
||||||
VALUE: '{{Değer|değer}}',
|
VALUE: '{{Değer|değer}}',
|
||||||
SHOW_FAV: 'sadece favorileri göster',
|
SHOW_FAV: 'sadece favorileri göster',
|
||||||
DEVICE_SENSOR_DATA: 'Cihaz ve Sensör Bilgisi',
|
DEVICE_DATA: 'Cihaz Bilgisi',
|
||||||
DEVICES_SENSORS: 'Cihazlar & Sensörler',
|
SENSOR_DATA: 'Sensör Bilgisi',
|
||||||
ATTACHED_SENSORS: 'Eklenmiş EMS-ESP Sensörler',
|
DEVICES: 'Cihazlar',
|
||||||
|
SENSORS: 'Sensörler',
|
||||||
RUN_COMMAND: 'Çalıştırma Komutu',
|
RUN_COMMAND: 'Çalıştırma Komutu',
|
||||||
CHANGE_VALUE: 'Değeri Değiştir',
|
CHANGE_VALUE: 'Değeri Değiştir',
|
||||||
CANCEL: 'İptal',
|
CANCEL: 'İptal',
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { Tab } from '@mui/material';
|
import { Tab } from '@mui/material';
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
import DashboardData from './DashboardData';
|
|
||||||
|
import DashboardDevices from './DashboardDevices';
|
||||||
|
import DashboardSensors from './DashboardSensors';
|
||||||
import DashboardStatus from './DashboardStatus';
|
import DashboardStatus from './DashboardStatus';
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
|
|
||||||
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
||||||
@@ -17,13 +20,15 @@ const Dashboard: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterTabs value={routerTab}>
|
<RouterTabs value={routerTab}>
|
||||||
<Tab value="data" label={LL.DEVICES_SENSORS()} />
|
<Tab value="devices" label={LL.DEVICES()} />
|
||||||
|
<Tab value="sensors" label={LL.SENSORS()} />
|
||||||
<Tab value="status" label="Status" />
|
<Tab value="status" label="Status" />
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="data" element={<DashboardData />} />
|
<Route path="devices" element={<DashboardDevices />} />
|
||||||
|
<Route path="sensors" element={<DashboardSensors />} />
|
||||||
<Route path="status" element={<DashboardStatus />} />
|
<Route path="status" element={<DashboardStatus />} />
|
||||||
<Route path="/*" element={<Navigate replace to="data" />} />
|
<Route path="/*" element={<Navigate replace to="devices" />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ import DeviceIcon from './DeviceIcon';
|
|||||||
|
|
||||||
import * as EMSESP from './api';
|
import * as EMSESP from './api';
|
||||||
|
|
||||||
import { DeviceValueUOM, DeviceValueUOM_s, AnalogType, AnalogTypeNames, DeviceEntityMask } from './types';
|
import { DeviceValueUOM, DeviceValueUOM_s, DeviceEntityMask } from './types';
|
||||||
import type { SensorData, Device, CoreData, DeviceData, DeviceValue, Sensor, Analog } from './types';
|
import type { SensorData, Device, CoreData, DeviceData, DeviceValue, TemperatureSensor, AnalogSensor } from './types';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components';
|
import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
@@ -54,26 +54,22 @@ import { AuthenticatedContext } from 'contexts/authentication';
|
|||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { numberValue, updateValue, extractErrorMessage } from 'utils';
|
import { numberValue, updateValue, extractErrorMessage } from 'utils';
|
||||||
|
|
||||||
const DashboardData: FC = () => {
|
const DashboardDevices: FC = () => {
|
||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const [coreData, setCoreData] = useState<CoreData>({
|
|
||||||
connected: true,
|
|
||||||
devices: [],
|
|
||||||
s_n: '',
|
|
||||||
active_sensors: 0,
|
|
||||||
analog_enabled: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const [deviceData, setDeviceData] = useState<DeviceData>({ label: '', data: [] });
|
const [deviceData, setDeviceData] = useState<DeviceData>({ label: '', data: [] });
|
||||||
const [sensorData, setSensorData] = useState<SensorData>({ sensors: [], analogs: [] });
|
|
||||||
const [deviceValue, setDeviceValue] = useState<DeviceValue>();
|
const [deviceValue, setDeviceValue] = useState<DeviceValue>();
|
||||||
const [sensor, setSensor] = useState<Sensor>();
|
|
||||||
const [analog, setAnalog] = useState<Analog>();
|
|
||||||
const [deviceDialog, setDeviceDialog] = useState<number>(-1);
|
const [deviceDialog, setDeviceDialog] = useState<number>(-1);
|
||||||
const [onlyFav, setOnlyFav] = useState(false);
|
const [onlyFav, setOnlyFav] = useState(false);
|
||||||
|
const [coreData, setCoreData] = useState<CoreData>({
|
||||||
|
connected: true,
|
||||||
|
devices: []
|
||||||
|
});
|
||||||
|
const [selectedDevice, setSelectedDevice] = useState<number>();
|
||||||
|
|
||||||
|
const [sensorData, setSensorData] = useState<SensorData>({ ts: [], as: [] });
|
||||||
|
const [analog, setAnalog] = useState<AnalogSensor>();
|
||||||
|
const [sensor, setSensor] = useState<TemperatureSensor>();
|
||||||
|
|
||||||
const common_theme = useTheme({
|
const common_theme = useTheme({
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
@@ -168,25 +164,6 @@ const DashboardData: FC = () => {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const temperature_theme = useTheme([data_theme]);
|
|
||||||
|
|
||||||
const analog_theme = useTheme([
|
|
||||||
data_theme,
|
|
||||||
{
|
|
||||||
Table: `
|
|
||||||
--data-table-library_grid-template-columns: 80px repeat(1, minmax(0, 1fr)) 120px 100px 40px;
|
|
||||||
`,
|
|
||||||
BaseCell: `
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
text-align: left;
|
|
||||||
},
|
|
||||||
&:nth-of-type(4) {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
const getSortIcon = (state: any, sortKey: any) => {
|
const getSortIcon = (state: any, sortKey: any) => {
|
||||||
if (state.sortKey === sortKey && state.reverse) {
|
if (state.sortKey === sortKey && state.reverse) {
|
||||||
return <KeyboardArrowDownOutlinedIcon />;
|
return <KeyboardArrowDownOutlinedIcon />;
|
||||||
@@ -197,41 +174,6 @@ const DashboardData: FC = () => {
|
|||||||
return <UnfoldMoreOutlinedIcon />;
|
return <UnfoldMoreOutlinedIcon />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const analog_sort = useSort(
|
|
||||||
{ nodes: sensorData.analogs },
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
sortIcon: {
|
|
||||||
iconDefault: <UnfoldMoreOutlinedIcon />,
|
|
||||||
iconUp: <KeyboardArrowUpOutlinedIcon />,
|
|
||||||
iconDown: <KeyboardArrowDownOutlinedIcon />
|
|
||||||
},
|
|
||||||
sortToggleType: SortToggleType.AlternateWithReset,
|
|
||||||
sortFns: {
|
|
||||||
GPIO: (array) => array.sort((a, b) => a.g - b.g),
|
|
||||||
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
|
|
||||||
TYPE: (array) => array.sort((a, b) => a.t - b.t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const sensor_sort = useSort(
|
|
||||||
{ nodes: sensorData.sensors },
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
sortIcon: {
|
|
||||||
iconDefault: <UnfoldMoreOutlinedIcon />,
|
|
||||||
iconUp: <KeyboardArrowUpOutlinedIcon />,
|
|
||||||
iconDown: <KeyboardArrowDownOutlinedIcon />
|
|
||||||
},
|
|
||||||
sortToggleType: SortToggleType.AlternateWithReset,
|
|
||||||
sortFns: {
|
|
||||||
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
|
|
||||||
TEMPERATURE: (array) => array.sort((a, b) => a.t - b.t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const dv_sort = useSort(
|
const dv_sort = useSort(
|
||||||
{ nodes: deviceData.data },
|
{ nodes: deviceData.data },
|
||||||
{},
|
{},
|
||||||
@@ -256,18 +198,17 @@ const DashboardData: FC = () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const fetchSensorData = async () => {
|
// const fetchSensorData = async () => {
|
||||||
try {
|
// try {
|
||||||
setSensorData((await EMSESP.readSensorData()).data);
|
// setSensorData((await EMSESP.readSensorData()).data);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
// toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const fetchDeviceData = async (id: string) => {
|
const fetchDeviceData = async (id: number) => {
|
||||||
const unique_id = parseInt(id);
|
|
||||||
try {
|
try {
|
||||||
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
setDeviceData((await EMSESP.readDeviceData({ id })).data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
@@ -285,29 +226,43 @@ const DashboardData: FC = () => {
|
|||||||
void fetchCoreData();
|
void fetchCoreData();
|
||||||
}, [fetchCoreData]);
|
}, [fetchCoreData]);
|
||||||
|
|
||||||
const refreshDataIndex = (selectedDevice: string) => {
|
// const refreshDataIndex = (selectedDevice: string) => {
|
||||||
if (selectedDevice === 'sensor') {
|
// // if (selectedDevice === 'sensor') {
|
||||||
void fetchSensorData();
|
// // void fetchSensorData();
|
||||||
return;
|
// // return;
|
||||||
}
|
// // }
|
||||||
|
|
||||||
setSensorData({ sensors: [], analogs: [] });
|
// // setSensorData({ sensors: [], analogs: [] });
|
||||||
|
// if (selectedDevice) {
|
||||||
|
// void fetchDeviceData(selectedDevice);
|
||||||
|
// } else {
|
||||||
|
// void fetchCoreData();
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const refreshData = () => {
|
||||||
|
// const selectedDevice = device_select.state.id;
|
||||||
|
// if (selectedDevice === 'sensor') {
|
||||||
|
// // void fetchSensorData();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// setSensorData({ sensors: [], analogs: [] });
|
||||||
if (selectedDevice) {
|
if (selectedDevice) {
|
||||||
void fetchDeviceData(selectedDevice);
|
void fetchDeviceData(selectedDevice);
|
||||||
} else {
|
} else {
|
||||||
void fetchCoreData();
|
void fetchCoreData();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const refreshData = () => {
|
// refreshDataIndex(device_select.state.id);
|
||||||
refreshDataIndex(device_select.state.id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function onSelectChange(action: any, state: any) {
|
function onSelectChange(action: any, state: any) {
|
||||||
|
setSelectedDevice(device_select.state.id);
|
||||||
if (action.type === 'ADD_BY_ID_EXCLUSIVELY') {
|
if (action.type === 'ADD_BY_ID_EXCLUSIVELY') {
|
||||||
refreshData();
|
refreshData();
|
||||||
} else {
|
} else {
|
||||||
setSensorData({ sensors: [], analogs: [] });
|
// setSensorData({ sensors: [], analogs: [] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +392,7 @@ const DashboardData: FC = () => {
|
|||||||
const sendDeviceValue = async () => {
|
const sendDeviceValue = async () => {
|
||||||
if (deviceValue) {
|
if (deviceValue) {
|
||||||
try {
|
try {
|
||||||
const response = await EMSESP.writeValue({
|
const response = await EMSESP.writeDeviceValue({
|
||||||
id: Number(device_select.state.id),
|
id: Number(device_select.state.id),
|
||||||
devicevalue: deviceValue
|
devicevalue: deviceValue
|
||||||
});
|
});
|
||||||
@@ -523,100 +478,6 @@ const DashboardData: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addAnalogSensor = () => {
|
|
||||||
setAnalog({ id: '0', g: 0, n: '', u: 0, v: 0, o: 0, t: 0, f: 1 });
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendSensor = async () => {
|
|
||||||
if (sensor) {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.writeSensor({
|
|
||||||
id: sensor.id,
|
|
||||||
name: sensor.n,
|
|
||||||
offset: sensor.o
|
|
||||||
});
|
|
||||||
if (response.status === 204) {
|
|
||||||
toast.error(LL.UPLOAD_OF(LL.SENSOR()) + ' ' + LL.FAILED());
|
|
||||||
} else if (response.status === 403) {
|
|
||||||
toast.error(LL.ACCESS_DENIED());
|
|
||||||
} else {
|
|
||||||
toast.success(LL.UPDATED_OF(LL.SENSOR()));
|
|
||||||
}
|
|
||||||
setSensor(undefined);
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
|
||||||
} finally {
|
|
||||||
setSensor(undefined);
|
|
||||||
await fetchSensorData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderSensorDialog = () => {
|
|
||||||
if (sensor) {
|
|
||||||
return (
|
|
||||||
<Dialog open={sensor !== undefined} onClose={() => setSensor(undefined)}>
|
|
||||||
<DialogTitle>
|
|
||||||
{LL.EDIT()} {LL.TEMP_SENSOR()}
|
|
||||||
</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
|
||||||
<Typography variant="body2">
|
|
||||||
{LL.ID_OF(LL.SENSOR())}: {sensor.id}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="n"
|
|
||||||
label={LL.ENTITY_NAME()}
|
|
||||||
value={sensor.n}
|
|
||||||
autoFocus
|
|
||||||
sx={{ width: '30ch' }}
|
|
||||||
onChange={updateValue(setSensor)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.OFFSET()}
|
|
||||||
value={numberValue(sensor.o)}
|
|
||||||
sx={{ width: '12ch' }}
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setSensor)}
|
|
||||||
inputProps={{ min: '-5', max: '5', step: '0.1' }}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: <InputAdornment position="start">°C</InputAdornment>
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button
|
|
||||||
startIcon={<CancelIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => setSensor(undefined)}
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<WarningIcon color="warning" />}
|
|
||||||
variant="contained"
|
|
||||||
type="submit"
|
|
||||||
onClick={() => sendSensor()}
|
|
||||||
color="info"
|
|
||||||
>
|
|
||||||
{LL.UPDATE()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderDeviceDialog = () => {
|
const renderDeviceDialog = () => {
|
||||||
if (coreData && coreData.devices.length > 0 && deviceDialog !== -1) {
|
if (coreData && coreData.devices.length > 0 && deviceDialog !== -1) {
|
||||||
return (
|
return (
|
||||||
@@ -692,21 +553,6 @@ const DashboardData: FC = () => {
|
|||||||
</Cell>
|
</Cell>
|
||||||
</Row>
|
</Row>
|
||||||
))}
|
))}
|
||||||
{(coreData.active_sensors > 0 || coreData.analog_enabled) && (
|
|
||||||
<Row key="sensor" item={{ id: 'sensor' }}>
|
|
||||||
<Cell>
|
|
||||||
<DeviceIcon type_id={1} />
|
|
||||||
</Cell>
|
|
||||||
<Cell>{coreData.s_n}</Cell>
|
|
||||||
<Cell>{LL.ATTACHED_SENSORS()}</Cell>
|
|
||||||
<Cell>{coreData.active_sensors}</Cell>
|
|
||||||
<Cell>
|
|
||||||
<IconButton size="small" onClick={() => addAnalogSensor()}>
|
|
||||||
<AddCircleOutlineOutlinedIcon sx={{ fontSize: 16, verticalAlign: 'middle' }} />
|
|
||||||
</IconButton>
|
|
||||||
</Cell>
|
|
||||||
</Row>
|
|
||||||
)}
|
|
||||||
</Body>
|
</Body>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -813,421 +659,13 @@ const DashboardData: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateSensor = (s: Sensor) => {
|
|
||||||
if (s && me.admin) {
|
|
||||||
setSensor(s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateAnalog = (a: Analog) => {
|
|
||||||
if (me.admin) {
|
|
||||||
setAnalog(a);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderDallasData = () => (
|
|
||||||
<>
|
|
||||||
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
|
||||||
{LL.TEMP_SENSORS()}
|
|
||||||
</Typography>
|
|
||||||
<Table
|
|
||||||
data={{ nodes: sensorData.sensors }}
|
|
||||||
theme={temperature_theme}
|
|
||||||
sort={sensor_sort}
|
|
||||||
layout={{ custom: true }}
|
|
||||||
>
|
|
||||||
{(tableList: any) => (
|
|
||||||
<>
|
|
||||||
<Header>
|
|
||||||
<HeaderRow>
|
|
||||||
<HeaderCell resize>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
|
||||||
endIcon={getSortIcon(sensor_sort.state, 'NAME')}
|
|
||||||
onClick={() => sensor_sort.fns.onToggleSort({ sortKey: 'NAME' })}
|
|
||||||
>
|
|
||||||
{LL.ENTITY_NAME()}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell stiff>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
|
||||||
endIcon={getSortIcon(sensor_sort.state, 'TEMPERATURE')}
|
|
||||||
onClick={() => sensor_sort.fns.onToggleSort({ sortKey: 'TEMPERATURE' })}
|
|
||||||
>
|
|
||||||
{LL.VALUE(0)}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell stiff />
|
|
||||||
</HeaderRow>
|
|
||||||
</Header>
|
|
||||||
<Body>
|
|
||||||
{tableList.map((s: Sensor) => (
|
|
||||||
<Row key={s.id} item={s} onClick={() => updateSensor(s)}>
|
|
||||||
<Cell>{s.n}</Cell>
|
|
||||||
<Cell>{formatValue(s.t, s.u)}</Cell>
|
|
||||||
<Cell>
|
|
||||||
{me.admin && (
|
|
||||||
<IconButton onClick={() => updateSensor(s)}>
|
|
||||||
<EditIcon color="primary" sx={{ fontSize: 16 }} />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</Cell>
|
|
||||||
</Row>
|
|
||||||
))}
|
|
||||||
</Body>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderAnalogData = () => (
|
|
||||||
<>
|
|
||||||
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
|
||||||
{LL.ANALOG_SENSORS()}
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Table data={{ nodes: sensorData.analogs }} theme={analog_theme} sort={analog_sort} layout={{ custom: true }}>
|
|
||||||
{(tableList: any) => (
|
|
||||||
<>
|
|
||||||
<Header>
|
|
||||||
<HeaderRow>
|
|
||||||
<HeaderCell stiff>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
|
||||||
endIcon={getSortIcon(analog_sort.state, 'GPIO')}
|
|
||||||
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'GPIO' })}
|
|
||||||
>
|
|
||||||
GPIO
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell resize>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
|
||||||
endIcon={getSortIcon(analog_sort.state, 'NAME')}
|
|
||||||
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'NAME' })}
|
|
||||||
>
|
|
||||||
{LL.ENTITY_NAME()}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell stiff>
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
|
||||||
endIcon={getSortIcon(analog_sort.state, 'TYPE')}
|
|
||||||
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'TYPE' })}
|
|
||||||
>
|
|
||||||
{LL.TYPE(0)}
|
|
||||||
</Button>
|
|
||||||
</HeaderCell>
|
|
||||||
<HeaderCell stiff>{LL.VALUE(0)}</HeaderCell>
|
|
||||||
<HeaderCell stiff />
|
|
||||||
</HeaderRow>
|
|
||||||
</Header>
|
|
||||||
<Body>
|
|
||||||
{tableList.map((a: Analog) => (
|
|
||||||
<Row key={a.id} item={a} onClick={() => updateAnalog(a)}>
|
|
||||||
<Cell stiff>{a.g}</Cell>
|
|
||||||
<Cell>{a.n}</Cell>
|
|
||||||
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
|
||||||
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
|
||||||
<Cell stiff>
|
|
||||||
{me.admin && (
|
|
||||||
<IconButton onClick={() => updateAnalog(a)}>
|
|
||||||
<EditIcon color="primary" sx={{ fontSize: 16 }} />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</Cell>
|
|
||||||
</Row>
|
|
||||||
))}
|
|
||||||
</Body>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Table>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
const sendRemoveAnalog = async () => {
|
|
||||||
if (analog) {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.writeAnalog({
|
|
||||||
gpio: analog.g,
|
|
||||||
name: analog.n,
|
|
||||||
offset: analog.o,
|
|
||||||
factor: analog.f,
|
|
||||||
uom: analog.u,
|
|
||||||
type: -1
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 204) {
|
|
||||||
toast.error(LL.DELETION_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED());
|
|
||||||
} else if (response.status === 403) {
|
|
||||||
toast.error(LL.ACCESS_DENIED());
|
|
||||||
} else {
|
|
||||||
toast.success(LL.REMOVED_OF(LL.ANALOG_SENSOR()));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
|
||||||
} finally {
|
|
||||||
setAnalog(undefined);
|
|
||||||
await fetchSensorData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendAnalog = async () => {
|
|
||||||
if (analog) {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.writeAnalog({
|
|
||||||
gpio: analog.g,
|
|
||||||
name: analog.n,
|
|
||||||
offset: analog.o,
|
|
||||||
factor: analog.f,
|
|
||||||
uom: analog.u,
|
|
||||||
type: analog.t
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 204) {
|
|
||||||
toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED());
|
|
||||||
} else if (response.status === 403) {
|
|
||||||
toast.error(LL.ACCESS_DENIED());
|
|
||||||
} else {
|
|
||||||
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR()));
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
|
||||||
} finally {
|
|
||||||
setAnalog(undefined);
|
|
||||||
await fetchSensorData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderAnalogDialog = () => {
|
|
||||||
if (analog) {
|
|
||||||
return (
|
|
||||||
<Dialog open={analog !== undefined} onClose={() => setAnalog(undefined)}>
|
|
||||||
<DialogTitle>
|
|
||||||
{LL.EDIT()} {LL.ANALOG_SENSOR()}
|
|
||||||
</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="n"
|
|
||||||
label={LL.ENTITY_NAME()}
|
|
||||||
value={analog.n}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="g"
|
|
||||||
label="GPIO"
|
|
||||||
value={numberValue(analog.g)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
autoFocus
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={8}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="t"
|
|
||||||
label={LL.TYPE(0)}
|
|
||||||
value={analog.t}
|
|
||||||
fullWidth
|
|
||||||
select
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
>
|
|
||||||
{AnalogTypeNames.map((val, i) => (
|
|
||||||
<MenuItem key={i} value={i}>
|
|
||||||
{val}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</ValidatedTextField>
|
|
||||||
</Grid>
|
|
||||||
{analog.t >= AnalogType.COUNTER && analog.t <= AnalogType.RATE && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="u"
|
|
||||||
label={LL.UNIT()}
|
|
||||||
value={analog.u}
|
|
||||||
fullWidth
|
|
||||||
select
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
>
|
|
||||||
{DeviceValueUOM_s.map((val, i) => (
|
|
||||||
<MenuItem key={i} value={i}>
|
|
||||||
{val}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</ValidatedTextField>
|
|
||||||
</Grid>
|
|
||||||
{analog.t === AnalogType.ADC && (
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.OFFSET()}
|
|
||||||
value={numberValue(analog.o)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ min: '0', max: '3300', step: '1' }}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: <InputAdornment position="start">mV</InputAdornment>
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{analog.t === AnalogType.COUNTER && (
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.STARTVALUE()}
|
|
||||||
value={numberValue(analog.o)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ step: '0.001' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="f"
|
|
||||||
label={LL.FACTOR()}
|
|
||||||
value={numberValue(analog.f)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ step: '0.001' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{analog.t === AnalogType.DIGITAL_OUT && (analog.g === 25 || analog.g === 26) && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.VALUE(0)}
|
|
||||||
value={numberValue(analog.o)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ min: '0', max: '255', step: '1' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{analog.t === AnalogType.DIGITAL_OUT && analog.g !== 25 && analog.g !== 26 && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.VALUE(0)}
|
|
||||||
value={numberValue(analog.o)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ min: '0', max: '1', step: '1' }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{analog.t >= AnalogType.PWM_0 && (
|
|
||||||
<>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="f"
|
|
||||||
label={LL.FREQ()}
|
|
||||||
value={numberValue(analog.f)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ min: '1', max: '5000', step: '1' }}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: <InputAdornment position="start">Hz</InputAdornment>
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<ValidatedTextField
|
|
||||||
name="o"
|
|
||||||
label={LL.DUTY_CYCLE()}
|
|
||||||
value={numberValue(analog.o)}
|
|
||||||
fullWidth
|
|
||||||
type="number"
|
|
||||||
variant="outlined"
|
|
||||||
onChange={updateValue(setAnalog)}
|
|
||||||
inputProps={{ min: '0', max: '100', step: '0.1' }}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: <InputAdornment position="start">%</InputAdornment>
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
<Box color="warning.main" mt={2}>
|
|
||||||
<Typography variant="body2">{LL.WARN_GPIO()}</Typography>
|
|
||||||
</Box>
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
|
|
||||||
<Button startIcon={<RemoveIcon />} variant="outlined" color="error" onClick={() => sendRemoveAnalog()}>
|
|
||||||
{LL.REMOVE()}
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
<Button
|
|
||||||
startIcon={<CancelIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => setAnalog(undefined)}
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<WarningIcon color="warning" />}
|
|
||||||
variant="contained"
|
|
||||||
type="submit"
|
|
||||||
onClick={() => sendAnalog()}
|
|
||||||
color="info"
|
|
||||||
>
|
|
||||||
{LL.UPDATE()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title={LL.DEVICE_SENSOR_DATA()} titleGutter>
|
<SectionContent title={LL.DEVICE_DATA()} titleGutter>
|
||||||
{renderCoreData()}
|
{renderCoreData()}
|
||||||
{renderDeviceData()}
|
{renderDeviceData()}
|
||||||
{renderDeviceDialog()}
|
{renderDeviceDialog()}
|
||||||
{sensorData.sensors.length !== 0 && renderDallasData()}
|
|
||||||
{sensorData.analogs.length !== 0 && renderAnalogData()}
|
|
||||||
{renderDeviceValueDialog()}
|
{renderDeviceValueDialog()}
|
||||||
{renderSensorDialog()}
|
|
||||||
{renderAnalogDialog()}
|
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={refreshData}>
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={refreshData}>
|
||||||
{LL.REFRESH()}
|
{LL.REFRESH()}
|
||||||
@@ -1242,4 +680,4 @@ const DashboardData: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DashboardData;
|
export default DashboardDevices;
|
||||||
469
interface/src/project/DashboardSensors.tsx
Normal file
469
interface/src/project/DashboardSensors.tsx
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined';
|
||||||
|
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
|
||||||
|
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
||||||
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
|
import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
|
||||||
|
import { Button, Typography, Box } from '@mui/material';
|
||||||
|
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
||||||
|
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||||
|
import { useTheme } from '@table-library/react-table-library/theme';
|
||||||
|
import { useState, useContext, useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import DashboardSensorsAnalogDialog from './DashboardSensorsAnalogDialog';
|
||||||
|
import DashboardSensorsTemperatureDialog from './DashboardSensorsTemperatureDialog';
|
||||||
|
import * as EMSESP from './api';
|
||||||
|
|
||||||
|
import { DeviceValueUOM, DeviceValueUOM_s, AnalogTypeNames } from './types';
|
||||||
|
import { temperatureSensorItemValidation, analogSensorItemValidation } from './validators';
|
||||||
|
import type { SensorData, TemperatureSensor, AnalogSensor } from './types';
|
||||||
|
import type { FC } from 'react';
|
||||||
|
import { ButtonRow, SectionContent } from 'components';
|
||||||
|
|
||||||
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { extractErrorMessage } from 'utils';
|
||||||
|
|
||||||
|
const DashboardSensors: FC = () => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
const [sensorData, setSensorData] = useState<SensorData>({ ts: [], as: [], analog_enabled: false });
|
||||||
|
const [selectedTemperatureSensor, setSelectedTemperatureSensor] = useState<TemperatureSensor>();
|
||||||
|
const [selectedAnalogSensor, setSelectedAnalogSensor] = useState<AnalogSensor>();
|
||||||
|
const [temperatureDialogOpen, setTemperatureDialogOpen] = useState<boolean>(false);
|
||||||
|
const [analogDialogOpen, setAnalogDialogOpen] = useState<boolean>(false);
|
||||||
|
const [creating, setCreating] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const isAdmin = me.admin;
|
||||||
|
|
||||||
|
const common_theme = useTheme({
|
||||||
|
BaseRow: `
|
||||||
|
font-size: 14px;
|
||||||
|
.td {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
HeaderRow: `
|
||||||
|
text-transform: uppercase;
|
||||||
|
background-color: black;
|
||||||
|
color: #90CAF9;
|
||||||
|
.th {
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
|
.th {
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
Row: `
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
.td {
|
||||||
|
padding: 8px;
|
||||||
|
border-top: 1px solid #565656;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
|
&.tr.tr-body.row-select.row-select-single-selected {
|
||||||
|
background-color: #3d4752;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
&:hover .td {
|
||||||
|
border-top: 1px solid #177ac9;
|
||||||
|
border-bottom: 1px solid #177ac9;
|
||||||
|
}
|
||||||
|
&:nth-of-type(odd) .td {
|
||||||
|
background-color: #303030;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
Cell: `
|
||||||
|
&:last-of-type {
|
||||||
|
text-align: right;
|
||||||
|
},
|
||||||
|
`
|
||||||
|
});
|
||||||
|
|
||||||
|
const temperature_theme = useTheme([
|
||||||
|
common_theme,
|
||||||
|
{
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: minmax(0, 1fr) 35%;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const analog_theme = useTheme([
|
||||||
|
common_theme,
|
||||||
|
{
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: 80px repeat(1, minmax(0, 1fr)) 120px 100px;
|
||||||
|
`
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fetchSensorData = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
setSensorData((await EMSESP.readSensorData()).data);
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
|
}
|
||||||
|
}, [LL]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void fetchSensorData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getSortIcon = (state: any, sortKey: any) => {
|
||||||
|
if (state.sortKey === sortKey && state.reverse) {
|
||||||
|
return <KeyboardArrowDownOutlinedIcon />;
|
||||||
|
}
|
||||||
|
if (state.sortKey === sortKey && !state.reverse) {
|
||||||
|
return <KeyboardArrowUpOutlinedIcon />;
|
||||||
|
}
|
||||||
|
return <UnfoldMoreOutlinedIcon />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const analog_sort = useSort(
|
||||||
|
{ nodes: sensorData.as },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
sortIcon: {
|
||||||
|
iconDefault: <UnfoldMoreOutlinedIcon />,
|
||||||
|
iconUp: <KeyboardArrowUpOutlinedIcon />,
|
||||||
|
iconDown: <KeyboardArrowDownOutlinedIcon />
|
||||||
|
},
|
||||||
|
sortToggleType: SortToggleType.AlternateWithReset,
|
||||||
|
sortFns: {
|
||||||
|
GPIO: (array) => array.sort((a, b) => a.g - b.g),
|
||||||
|
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
|
||||||
|
TYPE: (array) => array.sort((a, b) => a.t - b.t),
|
||||||
|
VALUE: (array) => array.sort((a, b) => a.v - b.v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const temperature_sort = useSort(
|
||||||
|
{ nodes: sensorData.ts },
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
sortIcon: {
|
||||||
|
iconDefault: <UnfoldMoreOutlinedIcon />,
|
||||||
|
iconUp: <KeyboardArrowUpOutlinedIcon />,
|
||||||
|
iconDown: <KeyboardArrowDownOutlinedIcon />
|
||||||
|
},
|
||||||
|
sortToggleType: SortToggleType.AlternateWithReset,
|
||||||
|
sortFns: {
|
||||||
|
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
|
||||||
|
VALUE: (array) => array.sort((a, b) => a.t - b.t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setInterval(() => fetchSensorData(), 60000);
|
||||||
|
return () => {
|
||||||
|
clearInterval(timer);
|
||||||
|
};
|
||||||
|
}, [fetchSensorData]);
|
||||||
|
|
||||||
|
const formatDurationMin = (duration_min: number) => {
|
||||||
|
const days = Math.trunc((duration_min * 60000) / 86400000);
|
||||||
|
const hours = Math.trunc((duration_min * 60000) / 3600000) % 24;
|
||||||
|
const minutes = Math.trunc((duration_min * 60000) / 60000) % 60;
|
||||||
|
|
||||||
|
let formatted = '';
|
||||||
|
if (days) {
|
||||||
|
formatted += LL.NUM_DAYS({ num: days }) + ' ';
|
||||||
|
}
|
||||||
|
if (hours) {
|
||||||
|
formatted += LL.NUM_HOURS({ num: hours }) + ' ';
|
||||||
|
}
|
||||||
|
if (minutes) {
|
||||||
|
formatted += LL.NUM_MINUTES({ num: minutes });
|
||||||
|
}
|
||||||
|
return formatted;
|
||||||
|
};
|
||||||
|
|
||||||
|
function formatValue(value: any, uom: number) {
|
||||||
|
if (value === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
switch (uom) {
|
||||||
|
case DeviceValueUOM.HOURS:
|
||||||
|
return value ? formatDurationMin(value * 60) : LL.NUM_HOURS({ num: 0 });
|
||||||
|
case DeviceValueUOM.MINUTES:
|
||||||
|
return value ? formatDurationMin(value) : LL.NUM_MINUTES({ num: 0 });
|
||||||
|
case DeviceValueUOM.SECONDS:
|
||||||
|
return LL.NUM_SECONDS({ num: value });
|
||||||
|
case DeviceValueUOM.NONE:
|
||||||
|
if (typeof value === 'number') {
|
||||||
|
return new Intl.NumberFormat().format(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
case DeviceValueUOM.DEGREES:
|
||||||
|
case DeviceValueUOM.DEGREES_R:
|
||||||
|
case DeviceValueUOM.FAHRENHEIT:
|
||||||
|
return (
|
||||||
|
new Intl.NumberFormat(undefined, {
|
||||||
|
minimumFractionDigits: 1
|
||||||
|
}).format(value) +
|
||||||
|
' ' +
|
||||||
|
DeviceValueUOM_s[uom]
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return new Intl.NumberFormat().format(value) + ' ' + DeviceValueUOM_s[uom];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateTemperatureSensor = (ts: TemperatureSensor) => {
|
||||||
|
if (isAdmin) {
|
||||||
|
setSelectedTemperatureSensor(ts);
|
||||||
|
setTemperatureDialogOpen(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTemperatureDialogClose = () => {
|
||||||
|
setTemperatureDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onTemperatureDialogSave = async (ts: TemperatureSensor) => {
|
||||||
|
try {
|
||||||
|
const response = await EMSESP.writeTemperatureSensor({
|
||||||
|
id: ts.id,
|
||||||
|
name: ts.n,
|
||||||
|
offset: ts.o
|
||||||
|
});
|
||||||
|
if (response.status === 204) {
|
||||||
|
toast.error(LL.UPLOAD_OF(LL.SENSOR()) + ' ' + LL.FAILED());
|
||||||
|
} else if (response.status === 403) {
|
||||||
|
toast.error(LL.ACCESS_DENIED());
|
||||||
|
} else {
|
||||||
|
toast.success(LL.UPDATED_OF(LL.SENSOR()));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
|
} finally {
|
||||||
|
setTemperatureDialogOpen(false);
|
||||||
|
setSelectedTemperatureSensor(undefined);
|
||||||
|
await fetchSensorData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateAnalogSensor = (as: AnalogSensor) => {
|
||||||
|
if (isAdmin) {
|
||||||
|
setCreating(false);
|
||||||
|
setSelectedAnalogSensor(as);
|
||||||
|
setAnalogDialogOpen(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAnalogDialogClose = () => {
|
||||||
|
setAnalogDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addAnalogSensor = () => {
|
||||||
|
setCreating(true);
|
||||||
|
setSelectedAnalogSensor({
|
||||||
|
id: Math.floor(Math.random() * (Math.floor(200) - 100) + 100),
|
||||||
|
n: '',
|
||||||
|
g: 40,
|
||||||
|
u: 0,
|
||||||
|
v: 0,
|
||||||
|
o: 0,
|
||||||
|
t: 0,
|
||||||
|
f: 1,
|
||||||
|
d: false
|
||||||
|
});
|
||||||
|
setAnalogDialogOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAnalogDialogSave = async (as: AnalogSensor) => {
|
||||||
|
try {
|
||||||
|
const response = await EMSESP.writeAnalogSensor({
|
||||||
|
id: as.id,
|
||||||
|
gpio: as.g,
|
||||||
|
name: as.n,
|
||||||
|
offset: as.o,
|
||||||
|
factor: as.f,
|
||||||
|
uom: as.u,
|
||||||
|
type: as.t,
|
||||||
|
deleted: as.d
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status === 204) {
|
||||||
|
toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED());
|
||||||
|
} else if (response.status === 403) {
|
||||||
|
toast.error(LL.ACCESS_DENIED());
|
||||||
|
} else {
|
||||||
|
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR()));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
|
} finally {
|
||||||
|
setAnalogDialogOpen(false);
|
||||||
|
setSelectedAnalogSensor(undefined);
|
||||||
|
await fetchSensorData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const RenderTemperatureSensors = () => (
|
||||||
|
<Table data={{ nodes: sensorData.ts }} theme={temperature_theme} sort={temperature_sort} layout={{ custom: true }}>
|
||||||
|
{(tableList: any) => (
|
||||||
|
<>
|
||||||
|
<Header>
|
||||||
|
<HeaderRow>
|
||||||
|
<HeaderCell resize>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
|
endIcon={getSortIcon(temperature_sort.state, 'NAME')}
|
||||||
|
onClick={() => temperature_sort.fns.onToggleSort({ sortKey: 'NAME' })}
|
||||||
|
>
|
||||||
|
{LL.NAME(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
||||||
|
endIcon={getSortIcon(temperature_sort.state, 'VALUE')}
|
||||||
|
onClick={() => temperature_sort.fns.onToggleSort({ sortKey: 'VALUE' })}
|
||||||
|
>
|
||||||
|
{LL.VALUE(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
</HeaderRow>
|
||||||
|
</Header>
|
||||||
|
<Body>
|
||||||
|
{tableList.map((ts: TemperatureSensor) => (
|
||||||
|
<Row key={ts.id} item={ts} onClick={() => updateTemperatureSensor(ts)}>
|
||||||
|
<Cell>{ts.n}</Cell>
|
||||||
|
<Cell>{formatValue(ts.t, ts.u)}</Cell>
|
||||||
|
</Row>
|
||||||
|
))}
|
||||||
|
</Body>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
|
||||||
|
const RenderAnalogSensors = () => (
|
||||||
|
<Table data={{ nodes: sensorData.as }} theme={analog_theme} sort={analog_sort} layout={{ custom: true }}>
|
||||||
|
{(tableList: any) => (
|
||||||
|
<>
|
||||||
|
<Header>
|
||||||
|
<HeaderRow>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
|
endIcon={getSortIcon(analog_sort.state, 'GPIO')}
|
||||||
|
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'GPIO' })}
|
||||||
|
>
|
||||||
|
GPIO
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
<HeaderCell resize>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
|
endIcon={getSortIcon(analog_sort.state, 'NAME')}
|
||||||
|
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'NAME' })}
|
||||||
|
>
|
||||||
|
{LL.NAME(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
|
endIcon={getSortIcon(analog_sort.state, 'TYPE')}
|
||||||
|
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'TYPE' })}
|
||||||
|
>
|
||||||
|
{LL.TYPE(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
<HeaderCell stiff>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
||||||
|
endIcon={getSortIcon(analog_sort.state, 'VALUE')}
|
||||||
|
onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'VALUE' })}
|
||||||
|
>
|
||||||
|
{LL.VALUE(0)}
|
||||||
|
</Button>
|
||||||
|
</HeaderCell>
|
||||||
|
</HeaderRow>
|
||||||
|
</Header>
|
||||||
|
<Body>
|
||||||
|
{tableList.map((a: AnalogSensor) => (
|
||||||
|
<Row key={a.id} item={a} onClick={() => updateAnalogSensor(a)}>
|
||||||
|
<Cell stiff>{a.g}</Cell>
|
||||||
|
<Cell>{a.n}</Cell>
|
||||||
|
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
||||||
|
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
||||||
|
</Row>
|
||||||
|
))}
|
||||||
|
</Body>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SectionContent title={LL.SENSOR_DATA()} titleGutter>
|
||||||
|
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
||||||
|
{LL.TEMP_SENSORS()}
|
||||||
|
</Typography>
|
||||||
|
<RenderTemperatureSensors />
|
||||||
|
{selectedTemperatureSensor && (
|
||||||
|
<DashboardSensorsTemperatureDialog
|
||||||
|
open={temperatureDialogOpen}
|
||||||
|
onClose={onTemperatureDialogClose}
|
||||||
|
onSave={onTemperatureDialogSave}
|
||||||
|
selectedItem={selectedTemperatureSensor}
|
||||||
|
validator={temperatureSensorItemValidation()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{sensorData?.analog_enabled === true && (
|
||||||
|
<>
|
||||||
|
<Typography sx={{ pt: 4, pb: 1 }} variant="h6" color="secondary">
|
||||||
|
{LL.ANALOG_SENSORS()}
|
||||||
|
</Typography>
|
||||||
|
<RenderAnalogSensors />
|
||||||
|
{selectedAnalogSensor && (
|
||||||
|
<DashboardSensorsAnalogDialog
|
||||||
|
open={analogDialogOpen}
|
||||||
|
onClose={onAnalogDialogClose}
|
||||||
|
onSave={onAnalogDialogSave}
|
||||||
|
creating={creating}
|
||||||
|
selectedItem={selectedAnalogSensor}
|
||||||
|
validator={analogSensorItemValidation(sensorData.as, creating)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ButtonRow>
|
||||||
|
<Box display="flex" flexWrap="wrap">
|
||||||
|
<Box flexGrow={1}>
|
||||||
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={fetchSensorData}>
|
||||||
|
{LL.REFRESH()}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
startIcon={<AddCircleOutlineOutlinedIcon />}
|
||||||
|
onClick={addAnalogSensor}
|
||||||
|
>
|
||||||
|
{LL.ADD(0) + ' ' + LL.ANALOG_SENSOR()}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</ButtonRow>
|
||||||
|
</SectionContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DashboardSensors;
|
||||||
261
interface/src/project/DashboardSensorsAnalogDialog.tsx
Normal file
261
interface/src/project/DashboardSensorsAnalogDialog.tsx
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
InputAdornment,
|
||||||
|
Grid,
|
||||||
|
MenuItem,
|
||||||
|
TextField
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import { AnalogType, AnalogTypeNames, DeviceValueUOM_s } from './types';
|
||||||
|
import type { AnalogSensor } from './types';
|
||||||
|
import type Schema from 'async-validator';
|
||||||
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
|
import { ValidatedTextField } from 'components';
|
||||||
|
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { numberValue, updateValue } from 'utils';
|
||||||
|
|
||||||
|
import { validate } from 'validators';
|
||||||
|
|
||||||
|
type DashboardSensorsAnalogDialogProps = {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSave: (as: AnalogSensor) => void;
|
||||||
|
creating: boolean;
|
||||||
|
selectedItem: AnalogSensor;
|
||||||
|
validator: Schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DashboardSensorsAnalogDialog = ({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
creating,
|
||||||
|
selectedItem,
|
||||||
|
validator
|
||||||
|
}: DashboardSensorsAnalogDialogProps) => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
const [editItem, setEditItem] = useState<AnalogSensor>(selectedItem);
|
||||||
|
const updateFormValue = updateValue(setEditItem);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
setEditItem(selectedItem);
|
||||||
|
}
|
||||||
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
try {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
await validate(validator, editItem);
|
||||||
|
onSave(editItem);
|
||||||
|
} catch (errors: any) {
|
||||||
|
setFieldErrors(errors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remove = () => {
|
||||||
|
editItem.d = true;
|
||||||
|
onSave(editItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={close}>
|
||||||
|
<DialogTitle>
|
||||||
|
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()} {LL.ANALOG_SENSOR()}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="n"
|
||||||
|
label={LL.NAME(0)}
|
||||||
|
value={editItem.n}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="g"
|
||||||
|
label="GPIO"
|
||||||
|
value={numberValue(editItem.g)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
autoFocus
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={8}>
|
||||||
|
<TextField name="t" label={LL.TYPE(0)} value={editItem.t} fullWidth select onChange={updateFormValue}>
|
||||||
|
{AnalogTypeNames.map((val, i) => (
|
||||||
|
<MenuItem key={i} value={i}>
|
||||||
|
{val}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
{editItem.t >= AnalogType.COUNTER && editItem.t <= AnalogType.RATE && (
|
||||||
|
<>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField name="u" label={LL.UNIT()} value={editItem.u} fullWidth select onChange={updateFormValue}>
|
||||||
|
{DeviceValueUOM_s.map((val, i) => (
|
||||||
|
<MenuItem key={i} value={i}>
|
||||||
|
{val}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
</Grid>
|
||||||
|
{editItem.t === AnalogType.ADC && (
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.OFFSET()}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '0', max: '3300', step: '1' }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">mV</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{editItem.t === AnalogType.COUNTER && (
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.STARTVALUE()}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ step: '0.001' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="f"
|
||||||
|
label={LL.FACTOR()}
|
||||||
|
value={numberValue(editItem.f)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ step: '0.001' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{editItem.t === AnalogType.DIGITAL_OUT && (editItem.g === 25 || editItem.g === 26) && (
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.VALUE(0)}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '0', max: '255', step: '1' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{editItem.t === AnalogType.DIGITAL_OUT && editItem.g !== 25 && editItem.g !== 26 && (
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.VALUE(0)}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '0', max: '1', step: '1' }}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{editItem.t >= AnalogType.PWM_0 && (
|
||||||
|
<>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="f"
|
||||||
|
label={LL.FREQ()}
|
||||||
|
value={numberValue(editItem.f)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '1', max: '5000', step: '1' }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">Hz</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={4}>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.DUTY_CYCLE()}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '0', max: '100', step: '0.1' }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">%</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Box color="warning.main" mt={2}>
|
||||||
|
<Typography variant="body2">{LL.WARN_GPIO()}</Typography>
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
{!creating && (
|
||||||
|
<Box flexGrow={1} sx={{ '& button': { mt: 0 } }}>
|
||||||
|
<Button startIcon={<RemoveIcon />} variant="outlined" color="error" onClick={remove}>
|
||||||
|
{LL.REMOVE()}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button startIcon={<WarningIcon color="warning" />} variant="contained" onClick={save} color="info">
|
||||||
|
{creating ? LL.ADD(0) : LL.UPDATE()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DashboardSensorsAnalogDialog;
|
||||||
121
interface/src/project/DashboardSensorsTemperatureDialog.tsx
Normal file
121
interface/src/project/DashboardSensorsTemperatureDialog.tsx
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
InputAdornment,
|
||||||
|
Grid,
|
||||||
|
TextField
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import type { TemperatureSensor } from './types';
|
||||||
|
import type Schema from 'async-validator';
|
||||||
|
import type { ValidateFieldsError } from 'async-validator';
|
||||||
|
import { ValidatedTextField } from 'components';
|
||||||
|
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { numberValue, updateValue } from 'utils';
|
||||||
|
|
||||||
|
import { validate } from 'validators';
|
||||||
|
|
||||||
|
type DashboardSensorsTemperatureDialogProps = {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSave: (ts: TemperatureSensor) => void;
|
||||||
|
selectedItem: TemperatureSensor;
|
||||||
|
validator: Schema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DashboardSensorsTemperatureDialog = ({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
selectedItem,
|
||||||
|
validator
|
||||||
|
}: DashboardSensorsTemperatureDialogProps) => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
const [editItem, setEditItem] = useState<TemperatureSensor>(selectedItem);
|
||||||
|
const updateFormValue = updateValue(setEditItem);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
setEditItem(selectedItem);
|
||||||
|
}
|
||||||
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
try {
|
||||||
|
setFieldErrors(undefined);
|
||||||
|
await validate(validator, editItem);
|
||||||
|
onSave(editItem);
|
||||||
|
} catch (errors: any) {
|
||||||
|
setFieldErrors(errors);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={close}>
|
||||||
|
<DialogTitle>
|
||||||
|
{LL.EDIT()} {LL.TEMP_SENSOR()}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
||||||
|
<Typography variant="body2">
|
||||||
|
{LL.ID_OF(LL.SENSOR())}: {editItem.id}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item>
|
||||||
|
<ValidatedTextField
|
||||||
|
fieldErrors={fieldErrors}
|
||||||
|
name="n"
|
||||||
|
label={LL.NAME(0)}
|
||||||
|
value={editItem.n}
|
||||||
|
autoFocus
|
||||||
|
sx={{ width: '30ch' }}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<TextField
|
||||||
|
name="o"
|
||||||
|
label={LL.OFFSET()}
|
||||||
|
value={numberValue(editItem.o)}
|
||||||
|
sx={{ width: '12ch' }}
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={{ min: '-5', max: '5', step: '0.1' }}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">°C</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button startIcon={<WarningIcon color="warning" />} variant="contained" onClick={save} color="info">
|
||||||
|
{LL.UPDATE()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DashboardSensorsTemperatureDialog;
|
||||||
@@ -15,7 +15,7 @@ interface DeviceIconProps {
|
|||||||
// matches emsdevice.h DeviceType
|
// matches emsdevice.h DeviceType
|
||||||
const enum DeviceType {
|
const enum DeviceType {
|
||||||
SYSTEM = 0,
|
SYSTEM = 0,
|
||||||
DALLASSENSOR,
|
TEMPERATURESENSOR,
|
||||||
ANALOGSENSOR,
|
ANALOGSENSOR,
|
||||||
SCHEDULER,
|
SCHEDULER,
|
||||||
BOILER,
|
BOILER,
|
||||||
@@ -37,7 +37,7 @@ const enum DeviceType {
|
|||||||
|
|
||||||
const DeviceIcon: FC<DeviceIconProps> = ({ type_id }) => {
|
const DeviceIcon: FC<DeviceIconProps> = ({ type_id }) => {
|
||||||
switch (type_id) {
|
switch (type_id) {
|
||||||
case DeviceType.DALLASSENSOR:
|
case DeviceType.TEMPERATURESENSOR:
|
||||||
case DeviceType.ANALOGSENSOR:
|
case DeviceType.ANALOGSENSOR:
|
||||||
return <MdOutlineSensors />;
|
return <MdOutlineSensors />;
|
||||||
case DeviceType.BOILER:
|
case DeviceType.BOILER:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment } from '@mui/material';
|
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment, TextField } from '@mui/material';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<Box color="warning.main">
|
<Box color="warning.main">
|
||||||
<Typography variant="body2">{LL.BOARD_PROFILE_TEXT()}</Typography>
|
<Typography variant="body2">{LL.BOARD_PROFILE_TEXT()}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="board_profile"
|
name="board_profile"
|
||||||
label={LL.BOARD_PROFILE()}
|
label={LL.BOARD_PROFILE()}
|
||||||
value={data.board_profile}
|
value={data.board_profile}
|
||||||
@@ -148,7 +148,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem key={'CUSTOM'} value={'CUSTOM'}>
|
<MenuItem key={'CUSTOM'} value={'CUSTOM'}>
|
||||||
{LL.CUSTOM()}…
|
{LL.CUSTOM()}…
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
{data.board_profile === 'CUSTOM' && (
|
{data.board_profile === 'CUSTOM' && (
|
||||||
<>
|
<>
|
||||||
<Grid
|
<Grid
|
||||||
@@ -230,7 +230,7 @@ const SettingsApplication: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="phy_type"
|
name="phy_type"
|
||||||
label={LL.PHY_TYPE()}
|
label={LL.PHY_TYPE()}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -244,7 +244,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={0}>{LL.DISABLED(1)}</MenuItem>
|
<MenuItem value={0}>{LL.DISABLED(1)}</MenuItem>
|
||||||
<MenuItem value={1}>LAN8720</MenuItem>
|
<MenuItem value={1}>LAN8720</MenuItem>
|
||||||
<MenuItem value={2}>TLK110</MenuItem>
|
<MenuItem value={2}>TLK110</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.phy_type !== 0 && (
|
{data.phy_type !== 0 && (
|
||||||
@@ -257,7 +257,7 @@ const SettingsApplication: FC = () => {
|
|||||||
alignItems="flex-start"
|
alignItems="flex-start"
|
||||||
>
|
>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="eth_power"
|
name="eth_power"
|
||||||
label={LL.GPIO_OF('PHY Power') + ' (-1=' + LL.DISABLED(1) + ')'}
|
label={LL.GPIO_OF('PHY Power') + ' (-1=' + LL.DISABLED(1) + ')'}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -270,7 +270,7 @@ const SettingsApplication: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="eth_phy_addr"
|
name="eth_phy_addr"
|
||||||
label={LL.ADDRESS_OF('PHY I²C')}
|
label={LL.ADDRESS_OF('PHY I²C')}
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -283,7 +283,7 @@ const SettingsApplication: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="eth_clock_mode"
|
name="eth_clock_mode"
|
||||||
label="PHY Clk"
|
label="PHY Clk"
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -298,7 +298,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={1}>GPIO0_OUT</MenuItem>
|
<MenuItem value={1}>GPIO0_OUT</MenuItem>
|
||||||
<MenuItem value={2}>GPIO16_OUT</MenuItem>
|
<MenuItem value={2}>GPIO16_OUT</MenuItem>
|
||||||
<MenuItem value={3}>GPIO17_OUT</MenuItem>
|
<MenuItem value={3}>GPIO17_OUT</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
@@ -309,7 +309,7 @@ const SettingsApplication: FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="tx_mode"
|
name="tx_mode"
|
||||||
label={LL.TX_MODE()}
|
label={LL.TX_MODE()}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -324,10 +324,10 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={2}>EMS+</MenuItem>
|
<MenuItem value={2}>EMS+</MenuItem>
|
||||||
<MenuItem value={3}>HT3</MenuItem>
|
<MenuItem value={3}>HT3</MenuItem>
|
||||||
<MenuItem value={4}>{LL.HARDWARE()}</MenuItem>
|
<MenuItem value={4}>{LL.HARDWARE()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="ems_bus_id"
|
name="ems_bus_id"
|
||||||
label={LL.ID_OF(LL.EMS_BUS(1))}
|
label={LL.ID_OF(LL.EMS_BUS(1))}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -349,14 +349,14 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={0x4b}>Gateway 4 (0x4B)</MenuItem>
|
<MenuItem value={0x4b}>Gateway 4 (0x4B)</MenuItem>
|
||||||
<MenuItem value={0x4c}>Gateway 5 (0x4C)</MenuItem>
|
<MenuItem value={0x4c}>Gateway 5 (0x4C)</MenuItem>
|
||||||
<MenuItem value={0x4d}>Gateway 7 (0x4D)</MenuItem>
|
<MenuItem value={0x4d}>Gateway 7 (0x4D)</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.GENERAL_OPTIONS()}
|
{LL.GENERAL_OPTIONS()}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Grid item>
|
<Grid item>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="locale"
|
name="locale"
|
||||||
label={LL.LANGUAGE_ENTITIES()}
|
label={LL.LANGUAGE_ENTITIES()}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
@@ -376,7 +376,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value="pl">Polski (PL)</MenuItem>
|
<MenuItem value="pl">Polski (PL)</MenuItem>
|
||||||
<MenuItem value="sv">Svenska (SV)</MenuItem>
|
<MenuItem value="sv">Svenska (SV)</MenuItem>
|
||||||
<MenuItem value="tr">Türk (TR)</MenuItem>
|
<MenuItem value="tr">Türk (TR)</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.led_gpio !== 0 && (
|
{data.led_gpio !== 0 && (
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
@@ -478,7 +478,7 @@ const SettingsApplication: FC = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="bool_dashboard"
|
name="bool_dashboard"
|
||||||
label={LL.BOOLEAN_FORMAT_DASHBOARD()}
|
label={LL.BOOLEAN_FORMAT_DASHBOARD()}
|
||||||
value={data.bool_dashboard}
|
value={data.bool_dashboard}
|
||||||
@@ -492,10 +492,10 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={2}>{LL.ONOFF_CAP()}</MenuItem>
|
<MenuItem value={2}>{LL.ONOFF_CAP()}</MenuItem>
|
||||||
<MenuItem value={3}>true/false</MenuItem>
|
<MenuItem value={3}>true/false</MenuItem>
|
||||||
<MenuItem value={5}>1/0</MenuItem>
|
<MenuItem value={5}>1/0</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="bool_format"
|
name="bool_format"
|
||||||
label={LL.BOOLEAN_FORMAT_API()}
|
label={LL.BOOLEAN_FORMAT_API()}
|
||||||
value={data.bool_format}
|
value={data.bool_format}
|
||||||
@@ -511,10 +511,10 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={4}>true/false</MenuItem>
|
<MenuItem value={4}>true/false</MenuItem>
|
||||||
<MenuItem value={5}>"1"/"0"</MenuItem>
|
<MenuItem value={5}>"1"/"0"</MenuItem>
|
||||||
<MenuItem value={6}>1/0</MenuItem>
|
<MenuItem value={6}>1/0</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6} md={4}>
|
<Grid item xs={12} sm={6} md={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="enum_format"
|
name="enum_format"
|
||||||
label={LL.ENUM_FORMAT()}
|
label={LL.ENUM_FORMAT()}
|
||||||
value={data.enum_format}
|
value={data.enum_format}
|
||||||
@@ -526,7 +526,7 @@ const SettingsApplication: FC = () => {
|
|||||||
>
|
>
|
||||||
<MenuItem value={1}>{LL.VALUE(1)}</MenuItem>
|
<MenuItem value={1}>{LL.VALUE(1)}</MenuItem>
|
||||||
<MenuItem value={2}>{LL.INDEX()}</MenuItem>
|
<MenuItem value={2}>{LL.INDEX()}</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{data.dallas_gpio !== 0 && (
|
{data.dallas_gpio !== 0 && (
|
||||||
@@ -590,7 +590,7 @@ const SettingsApplication: FC = () => {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="syslog_level"
|
name="syslog_level"
|
||||||
label={LL.LOG_LEVEL()}
|
label={LL.LOG_LEVEL()}
|
||||||
value={data.syslog_level}
|
value={data.syslog_level}
|
||||||
@@ -607,7 +607,7 @@ const SettingsApplication: FC = () => {
|
|||||||
<MenuItem value={6}>INFO</MenuItem>
|
<MenuItem value={6}>INFO</MenuItem>
|
||||||
<MenuItem value={7}>DEBUG</MenuItem>
|
<MenuItem value={7}>DEBUG</MenuItem>
|
||||||
<MenuItem value={9}>ALL</MenuItem>
|
<MenuItem value={9}>ALL</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} sm={6}>
|
<Grid item xs={12} sm={6}>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
@@ -635,7 +635,6 @@ const SettingsApplication: FC = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</MessageBox>
|
</MessageBox>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!restartNeeded && dirtyFlags && dirtyFlags.length !== 0 && (
|
{!restartNeeded && dirtyFlags && dirtyFlags.length !== 0 && (
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -156,7 +156,6 @@ const SettingsCustomization: FC = () => {
|
|||||||
}
|
}
|
||||||
}, [LL]);
|
}, [LL]);
|
||||||
|
|
||||||
// on mount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void fetchDevices();
|
void fetchDevices();
|
||||||
}, [fetchDevices]);
|
}, [fetchDevices]);
|
||||||
@@ -580,7 +579,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
open={dialogOpen}
|
open={dialogOpen}
|
||||||
onClose={onDialogClose}
|
onClose={onDialogClose}
|
||||||
onSave={onDialogSave}
|
onSave={onDialogSave}
|
||||||
selectedDeviceEntity={selectedDeviceEntity}
|
selectedItem={selectedDeviceEntity}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
|
|||||||
@@ -26,17 +26,12 @@ type SettingsCustomizationDialogProps = {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (di: DeviceEntity) => void;
|
onSave: (di: DeviceEntity) => void;
|
||||||
selectedDeviceEntity: DeviceEntity;
|
selectedItem: DeviceEntity;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsCustomizationDialog = ({
|
const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: SettingsCustomizationDialogProps) => {
|
||||||
open,
|
|
||||||
onClose,
|
|
||||||
onSave,
|
|
||||||
selectedDeviceEntity
|
|
||||||
}: SettingsCustomizationDialogProps) => {
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [editItem, setEditItem] = useState<DeviceEntity>(selectedDeviceEntity);
|
const [editItem, setEditItem] = useState<DeviceEntity>(selectedItem);
|
||||||
const [error, setError] = useState<boolean>(false);
|
const [error, setError] = useState<boolean>(false);
|
||||||
|
|
||||||
const updateFormValue = updateValue(setEditItem);
|
const updateFormValue = updateValue(setEditItem);
|
||||||
@@ -47,9 +42,9 @@ const SettingsCustomizationDialog = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
setError(false);
|
setError(false);
|
||||||
setEditItem(selectedDeviceEntity);
|
setEditItem(selectedItem);
|
||||||
}
|
}
|
||||||
}, [open, selectedDeviceEntity]);
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
onClose();
|
onClose();
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ const SettingsEntities: FC = () => {
|
|||||||
creating={creating}
|
creating={creating}
|
||||||
onClose={onDialogClose}
|
onClose={onDialogClose}
|
||||||
onSave={onDialogSave}
|
onSave={onDialogSave}
|
||||||
selectedEntityItem={selectedEntityItem}
|
selectedItem={selectedEntityItem}
|
||||||
validator={entityItemValidation()}
|
validator={entityItemValidation()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
Grid,
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
MenuItem
|
MenuItem,
|
||||||
|
TextField
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ type SettingsEntitiesDialogProps = {
|
|||||||
creating: boolean;
|
creating: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (ei: EntityItem) => void;
|
onSave: (ei: EntityItem) => void;
|
||||||
selectedEntityItem: EntityItem;
|
selectedItem: EntityItem;
|
||||||
validator: Schema;
|
validator: Schema;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,28 +43,26 @@ const SettingsEntitiesDialog = ({
|
|||||||
creating,
|
creating,
|
||||||
onClose,
|
onClose,
|
||||||
onSave,
|
onSave,
|
||||||
selectedEntityItem,
|
selectedItem,
|
||||||
validator
|
validator
|
||||||
}: SettingsEntitiesDialogProps) => {
|
}: SettingsEntitiesDialogProps) => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [editItem, setEditItem] = useState<EntityItem>(selectedEntityItem);
|
const [editItem, setEditItem] = useState<EntityItem>(selectedItem);
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setEditItem);
|
const updateFormValue = updateValue(setEditItem);
|
||||||
|
|
||||||
// on mount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
setFieldErrors(undefined);
|
setFieldErrors(undefined);
|
||||||
setEditItem(selectedEntityItem);
|
setEditItem(selectedItem);
|
||||||
// convert to hex strings straight away
|
// convert to hex strings straight away
|
||||||
setEditItem({
|
setEditItem({
|
||||||
...selectedEntityItem,
|
...selectedItem,
|
||||||
device_id: selectedEntityItem.device_id.toString(16).toUpperCase().slice(-2),
|
device_id: selectedItem.device_id.toString(16).toUpperCase().slice(-2),
|
||||||
type_id: selectedEntityItem.type_id.toString(16).toUpperCase().slice(-4)
|
type_id: selectedItem.type_id.toString(16).toUpperCase().slice(-4)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [open, selectedEntityItem]);
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
onClose();
|
onClose();
|
||||||
@@ -157,7 +156,7 @@ const SettingsEntitiesDialog = ({
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="value_type"
|
name="value_type"
|
||||||
label="Value Type"
|
label="Value Type"
|
||||||
value={editItem.value_type}
|
value={editItem.value_type}
|
||||||
@@ -174,13 +173,13 @@ const SettingsEntitiesDialog = ({
|
|||||||
<MenuItem value={4}>USHORT</MenuItem>
|
<MenuItem value={4}>USHORT</MenuItem>
|
||||||
<MenuItem value={5}>ULONG</MenuItem>
|
<MenuItem value={5}>ULONG</MenuItem>
|
||||||
<MenuItem value={6}>TIME</MenuItem>
|
<MenuItem value={6}>TIME</MenuItem>
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{editItem.value_type !== 0 && (
|
{editItem.value_type !== 0 && (
|
||||||
<>
|
<>
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="factor"
|
name="factor"
|
||||||
label={LL.FACTOR()}
|
label={LL.FACTOR()}
|
||||||
value={editItem.factor}
|
value={editItem.factor}
|
||||||
@@ -193,7 +192,7 @@ const SettingsEntitiesDialog = ({
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<ValidatedTextField
|
<TextField
|
||||||
name="uom"
|
name="uom"
|
||||||
label={LL.UNIT()}
|
label={LL.UNIT()}
|
||||||
value={editItem.uom}
|
value={editItem.uom}
|
||||||
@@ -207,7 +206,7 @@ const SettingsEntitiesDialog = ({
|
|||||||
{val}
|
{val}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</ValidatedTextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -270,7 +270,7 @@ const SettingsScheduler: FC = () => {
|
|||||||
creating={creating}
|
creating={creating}
|
||||||
onClose={onDialogClose}
|
onClose={onDialogClose}
|
||||||
onSave={onDialogSave}
|
onSave={onDialogSave}
|
||||||
selectedSchedulerItem={selectedScheduleItem}
|
selectedItem={selectedScheduleItem}
|
||||||
validator={schedulerItemValidation()}
|
validator={schedulerItemValidation()}
|
||||||
dow={dow}
|
dow={dow}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type SettingsSchedulerDialogProps = {
|
|||||||
creating: boolean;
|
creating: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (ei: ScheduleItem) => void;
|
onSave: (ei: ScheduleItem) => void;
|
||||||
selectedSchedulerItem: ScheduleItem;
|
selectedItem: ScheduleItem;
|
||||||
validator: Schema;
|
validator: Schema;
|
||||||
dow: string[];
|
dow: string[];
|
||||||
};
|
};
|
||||||
@@ -47,12 +47,12 @@ const SettingsSchedulerDialog = ({
|
|||||||
creating,
|
creating,
|
||||||
onClose,
|
onClose,
|
||||||
onSave,
|
onSave,
|
||||||
selectedSchedulerItem,
|
selectedItem,
|
||||||
validator,
|
validator,
|
||||||
dow
|
dow
|
||||||
}: SettingsSchedulerDialogProps) => {
|
}: SettingsSchedulerDialogProps) => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [editItem, setEditItem] = useState<ScheduleItem>(selectedSchedulerItem);
|
const [editItem, setEditItem] = useState<ScheduleItem>(selectedItem);
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
|
|
||||||
const updateFormValue = updateValue(setEditItem);
|
const updateFormValue = updateValue(setEditItem);
|
||||||
@@ -60,9 +60,9 @@ const SettingsSchedulerDialog = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
setFieldErrors(undefined);
|
setFieldErrors(undefined);
|
||||||
setEditItem(selectedSchedulerItem);
|
setEditItem(selectedItem);
|
||||||
}
|
}
|
||||||
}, [open, selectedSchedulerItem]);
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
onClose();
|
onClose();
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import type {
|
|||||||
DeviceEntity,
|
DeviceEntity,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
CustomEntities,
|
CustomEntities,
|
||||||
WriteValue,
|
WriteDeviceValue,
|
||||||
WriteSensor,
|
WriteTemperatureSensor,
|
||||||
WriteAnalog,
|
WriteAnalogSensor,
|
||||||
SensorData,
|
SensorData,
|
||||||
Schedule,
|
Schedule,
|
||||||
Entities
|
Entities
|
||||||
@@ -68,16 +68,16 @@ export function writeCustomEntities(customEntities: CustomEntities): AxiosPromis
|
|||||||
return AXIOS.post('/customEntities', customEntities);
|
return AXIOS.post('/customEntities', customEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeValue(writevalue: WriteValue): AxiosPromise<void> {
|
export function writeDeviceValue(dv: WriteDeviceValue): AxiosPromise<void> {
|
||||||
return AXIOS.post('/writeValue', writevalue);
|
return AXIOS.post('/writeDeviceValue', dv);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeSensor(writesensor: WriteSensor): AxiosPromise<void> {
|
export function writeTemperatureSensor(ts: WriteTemperatureSensor): AxiosPromise<void> {
|
||||||
return AXIOS.post('/writeSensor', writesensor);
|
return AXIOS.post('/writeTemperatureSensor', ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeAnalog(writeanalog: WriteAnalog): AxiosPromise<void> {
|
export function writeAnalogSensor(as: WriteAnalogSensor): AxiosPromise<void> {
|
||||||
return AXIOS.post('/writeAnalog', writeanalog);
|
return AXIOS.post('/writeAnalogSensor', as);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCustomizations(): AxiosPromise<void> {
|
export function resetCustomizations(): AxiosPromise<void> {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export interface Device {
|
|||||||
e: number; // number of entries
|
e: number; // number of entries
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Sensor {
|
export interface TemperatureSensor {
|
||||||
id: string; // id string
|
id: string; // id string
|
||||||
n: string; // name/alias
|
n: string; // name/alias
|
||||||
t?: number; // temp, optional
|
t?: number; // temp, optional
|
||||||
@@ -79,34 +79,33 @@ export interface Sensor {
|
|||||||
u: number; // uom
|
u: number; // uom
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Analog {
|
export interface AnalogSensor {
|
||||||
id: string; // id string
|
id: number;
|
||||||
g: number; // GPIO
|
g: number; // GPIO
|
||||||
n: string;
|
n: string;
|
||||||
v: number; // is optional
|
v: number;
|
||||||
u: number;
|
u: number;
|
||||||
o: number;
|
o: number;
|
||||||
f: number;
|
f: number;
|
||||||
t: number;
|
t: number;
|
||||||
|
d: boolean; // deleted flag
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WriteSensor {
|
export interface WriteTemperatureSensor {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
offset: number;
|
offset: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SensorData {
|
export interface SensorData {
|
||||||
sensors: Sensor[];
|
ts: TemperatureSensor[];
|
||||||
analogs: Analog[];
|
as: AnalogSensor[];
|
||||||
|
analog_enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CoreData {
|
export interface CoreData {
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
devices: Device[];
|
devices: Device[];
|
||||||
s_n: string;
|
|
||||||
active_sensors: number;
|
|
||||||
analog_enabled: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeviceShort {
|
export interface DeviceShort {
|
||||||
@@ -216,6 +215,7 @@ export const DeviceValueUOM_s = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export enum AnalogType {
|
export enum AnalogType {
|
||||||
|
REMOVED = -1,
|
||||||
NOTUSED = 0,
|
NOTUSED = 0,
|
||||||
DIGITAL_IN,
|
DIGITAL_IN,
|
||||||
COUNTER,
|
COUNTER,
|
||||||
@@ -281,18 +281,20 @@ export interface APIcall {
|
|||||||
id: any;
|
id: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WriteValue {
|
export interface WriteDeviceValue {
|
||||||
id: number;
|
id: number;
|
||||||
devicevalue: DeviceValue;
|
devicevalue: DeviceValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WriteAnalog {
|
export interface WriteAnalogSensor {
|
||||||
|
id: number;
|
||||||
gpio: number;
|
gpio: number;
|
||||||
name: string;
|
name: string;
|
||||||
factor: number;
|
factor: number;
|
||||||
offset: number;
|
offset: number;
|
||||||
uom: number;
|
uom: number;
|
||||||
type: number;
|
type: number;
|
||||||
|
deleted: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DeviceEntityMask {
|
export enum DeviceEntityMask {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Schema from 'async-validator';
|
import Schema from 'async-validator';
|
||||||
import type { Settings } from './types';
|
import type { AnalogSensor, Settings } from './types';
|
||||||
import type { InternalRuleItem } from 'async-validator';
|
import type { InternalRuleItem } from 'async-validator';
|
||||||
import { IP_OR_HOSTNAME_VALIDATOR } from 'validators/shared';
|
import { IP_OR_HOSTNAME_VALIDATOR } from 'validators/shared';
|
||||||
|
|
||||||
@@ -136,3 +136,28 @@ export const entityItemValidation = () =>
|
|||||||
{ type: 'number', min: 0, max: 255, message: 'Must be between 0 and 255' }
|
{ type: 'number', min: 0, max: 255, message: 'Must be between 0 and 255' }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const temperatureSensorItemValidation = () =>
|
||||||
|
new Schema({
|
||||||
|
n: [{ required: true, message: 'Name is required' }]
|
||||||
|
});
|
||||||
|
|
||||||
|
export const isGPIOUniqueValidator = (sensors: AnalogSensor[]) => ({
|
||||||
|
validator(rule: InternalRuleItem, gpio: number, callback: (error?: string) => void) {
|
||||||
|
if (sensors.find((as) => as.g === gpio)) {
|
||||||
|
callback('GPIO already in use');
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const analogSensorItemValidation = (sensors: AnalogSensor[], creating: boolean) =>
|
||||||
|
new Schema({
|
||||||
|
n: [{ required: true, message: 'Name is required' }],
|
||||||
|
g: [
|
||||||
|
{ required: true, message: 'GPIO is required' },
|
||||||
|
GPIO_VALIDATOR,
|
||||||
|
...(creating ? [isGPIOUniqueValidator(sensors)] : [])
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|||||||
@@ -251,9 +251,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/babel-plugin@npm:^11.10.6":
|
"@emotion/babel-plugin@npm:^11.10.8":
|
||||||
version: 11.10.6
|
version: 11.10.8
|
||||||
resolution: "@emotion/babel-plugin@npm:11.10.6"
|
resolution: "@emotion/babel-plugin@npm:11.10.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-module-imports": ^7.16.7
|
"@babel/helper-module-imports": ^7.16.7
|
||||||
"@babel/runtime": ^7.18.3
|
"@babel/runtime": ^7.18.3
|
||||||
@@ -265,12 +265,12 @@ __metadata:
|
|||||||
escape-string-regexp: ^4.0.0
|
escape-string-regexp: ^4.0.0
|
||||||
find-root: ^1.1.0
|
find-root: ^1.1.0
|
||||||
source-map: ^0.5.7
|
source-map: ^0.5.7
|
||||||
stylis: 4.1.3
|
stylis: 4.1.4
|
||||||
checksum: 734ab5d59f8a64ec2cb140f71483f74910ada115bf78ce5b645a9e3e379554ffd79045edb74efb8c1d8f856ef4d302bf8ac59b969b1cc28dedcd5000072e63ce
|
checksum: bb9b4c81623d64da91d9e7819c66ddef0d64159df92d74f01aaa79b42e69037d1dafdda3aecca6c14a18311c31852ad1171c5a32cc21146834681298cd1884ab
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.10.7":
|
"@emotion/cache@npm:^11.10.7":
|
||||||
version: 11.10.7
|
version: 11.10.7
|
||||||
resolution: "@emotion/cache@npm:11.10.7"
|
resolution: "@emotion/cache@npm:11.10.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -283,6 +283,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@emotion/cache@npm:^11.10.8":
|
||||||
|
version: 11.10.8
|
||||||
|
resolution: "@emotion/cache@npm:11.10.8"
|
||||||
|
dependencies:
|
||||||
|
"@emotion/memoize": ^0.8.0
|
||||||
|
"@emotion/sheet": ^1.2.1
|
||||||
|
"@emotion/utils": ^1.2.0
|
||||||
|
"@emotion/weak-memoize": ^0.3.0
|
||||||
|
stylis: 4.1.4
|
||||||
|
checksum: 6369883921b3c7d4598dfd584001922e8ef80aa7c373db6e5fb430b4ae9ecf3de1a2c2bcdbfef078821ea70a9413572f1263ce11b47082e2f532028d9e50ab9d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/hash@npm:^0.9.0":
|
"@emotion/hash@npm:^0.9.0":
|
||||||
version: 0.9.0
|
version: 0.9.0
|
||||||
resolution: "@emotion/hash@npm:0.9.0"
|
resolution: "@emotion/hash@npm:0.9.0"
|
||||||
@@ -306,13 +319,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/react@npm:^11.10.6":
|
"@emotion/react@npm:^11.10.8":
|
||||||
version: 11.10.6
|
version: 11.10.8
|
||||||
resolution: "@emotion/react@npm:11.10.6"
|
resolution: "@emotion/react@npm:11.10.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": ^7.18.3
|
"@babel/runtime": ^7.18.3
|
||||||
"@emotion/babel-plugin": ^11.10.6
|
"@emotion/babel-plugin": ^11.10.8
|
||||||
"@emotion/cache": ^11.10.5
|
"@emotion/cache": ^11.10.8
|
||||||
"@emotion/serialize": ^1.1.1
|
"@emotion/serialize": ^1.1.1
|
||||||
"@emotion/use-insertion-effect-with-fallbacks": ^1.0.0
|
"@emotion/use-insertion-effect-with-fallbacks": ^1.0.0
|
||||||
"@emotion/utils": ^1.2.0
|
"@emotion/utils": ^1.2.0
|
||||||
@@ -323,7 +336,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 4c5ce8ef279a8ce0d371414720d9b2b195ce6b30abf82d99a856ef3b7dc8643f8a32b9b01fded35d94ab9159e4982f7eb0ffa3c4b1aabb102180383e56232bcf
|
checksum: eba3e90ec0ce6b110c358632c63df885385293f4d1303af4f049a1ce2478c433b7db6406bcaf4526bca90b61bf38000d727647637fe5a9b84e625f222b203647
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -347,12 +360,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@emotion/styled@npm:^11.10.6":
|
"@emotion/styled@npm:^11.10.8":
|
||||||
version: 11.10.6
|
version: 11.10.8
|
||||||
resolution: "@emotion/styled@npm:11.10.6"
|
resolution: "@emotion/styled@npm:11.10.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": ^7.18.3
|
"@babel/runtime": ^7.18.3
|
||||||
"@emotion/babel-plugin": ^11.10.6
|
"@emotion/babel-plugin": ^11.10.8
|
||||||
"@emotion/is-prop-valid": ^1.2.0
|
"@emotion/is-prop-valid": ^1.2.0
|
||||||
"@emotion/serialize": ^1.1.1
|
"@emotion/serialize": ^1.1.1
|
||||||
"@emotion/use-insertion-effect-with-fallbacks": ^1.0.0
|
"@emotion/use-insertion-effect-with-fallbacks": ^1.0.0
|
||||||
@@ -363,7 +376,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 69e968bb359758ec454c547d6f1d5b1a50a8c149c13274119f63d81fbb76db46b2df53c236ecbc9cb15696f9834647156d715e5e6ccc84ff7b1852617e367386
|
checksum: 092493bd6155a45d10c88373fd38e8cfa3ac5ba8050333b714265f4c2f6d6012ce5e140627f6c8170f749407ac3bc9de7fc85d45c6de92fe6b1b7fb7cc24d8ad
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -694,9 +707,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/base@npm:5.0.0-alpha.126":
|
"@mui/base@npm:5.0.0-alpha.127":
|
||||||
version: 5.0.0-alpha.126
|
version: 5.0.0-alpha.127
|
||||||
resolution: "@mui/base@npm:5.0.0-alpha.126"
|
resolution: "@mui/base@npm:5.0.0-alpha.127"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": ^7.21.0
|
"@babel/runtime": ^7.21.0
|
||||||
"@emotion/is-prop-valid": ^1.2.0
|
"@emotion/is-prop-valid": ^1.2.0
|
||||||
@@ -713,14 +726,14 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: afb6b99cba541cdb40bb098a78d105721cd6c6db3156fe9923bbb0aea184f6949ab5db79ab95177b4edb011acb35ac34556124b1203fd91ea16f52dc5477da7b
|
checksum: 6b339fe6a7653e55d04442776adb13864916fdd1a16c3c40caafb72e0691f9e86a4e49820b0f2d92d84ce24daeb024a24ceed20275ab3dbf1f87493cc57bd0a3
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/core-downloads-tracker@npm:^5.12.1":
|
"@mui/core-downloads-tracker@npm:^5.12.2":
|
||||||
version: 5.12.1
|
version: 5.12.2
|
||||||
resolution: "@mui/core-downloads-tracker@npm:5.12.1"
|
resolution: "@mui/core-downloads-tracker@npm:5.12.2"
|
||||||
checksum: 0fc90f840e888e0a671ce43dfaa50018c7f2b82379b3adf3128387c3f29d06cdc235493939698339eb2aab49cf9a167473ed95f6a64eb424ee2d95849dd4aa76
|
checksum: 6d421c1758b99f416c2d7f61c838809e4bbf017da8ec26fe9198b3d10d41e1d0ea58bbf7ed016dca38d4c76300f94bf900dfd02fb34fb53f57492cffe1b57c65
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -740,13 +753,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mui/material@npm:^5.12.1":
|
"@mui/material@npm:^5.12.2":
|
||||||
version: 5.12.1
|
version: 5.12.2
|
||||||
resolution: "@mui/material@npm:5.12.1"
|
resolution: "@mui/material@npm:5.12.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": ^7.21.0
|
"@babel/runtime": ^7.21.0
|
||||||
"@mui/base": 5.0.0-alpha.126
|
"@mui/base": 5.0.0-alpha.127
|
||||||
"@mui/core-downloads-tracker": ^5.12.1
|
"@mui/core-downloads-tracker": ^5.12.2
|
||||||
"@mui/system": ^5.12.1
|
"@mui/system": ^5.12.1
|
||||||
"@mui/types": ^7.2.4
|
"@mui/types": ^7.2.4
|
||||||
"@mui/utils": ^5.12.0
|
"@mui/utils": ^5.12.0
|
||||||
@@ -769,7 +782,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: a4b4becea4da7af787d58b09afe6a3e1c7b1aa1b27f93186f848efd0bcb250e5b39ca51cdbcedc0216db32049665a69a13a2f8480d357f2310ca6efcf8b10a76
|
checksum: 35ef3e103d2ec1aa9fdbffd0df0097349dcb8eaf41add7c9c4ed023012c256bb07df2266e7c50fef67d6cbac61a86b7ad1baa9a791d0c8fcbfce1d2194becf43
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1198,9 +1211,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@table-library/react-table-library@npm:4.1.0":
|
"@table-library/react-table-library@npm:4.1.2":
|
||||||
version: 4.1.0
|
version: 4.1.2
|
||||||
resolution: "@table-library/react-table-library@npm:4.1.0"
|
resolution: "@table-library/react-table-library@npm:4.1.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
clsx: 1.1.1
|
clsx: 1.1.1
|
||||||
react-virtualized-auto-sizer: 1.0.7
|
react-virtualized-auto-sizer: 1.0.7
|
||||||
@@ -1209,7 +1222,7 @@ __metadata:
|
|||||||
"@emotion/react": ">= 11"
|
"@emotion/react": ">= 11"
|
||||||
react: ">=16.8.0"
|
react: ">=16.8.0"
|
||||||
react-dom: ">=16.8.0"
|
react-dom: ">=16.8.0"
|
||||||
checksum: e64571d6ad5b755abbef3e30dcb56aaa2362ffb26a7cbade56828cedec2532530ddf463a275d7d264ff6822d1191694153e63d9b3b13fcd3f540fa2b3d8a2b4e
|
checksum: 2c465d0369349f36d2114b6a397ae12588f64fd114677533f76b80569ff1401233bd26bd47ecda14375a6033fd68c76e686f4f57646b7754a2e6062265f84322
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1264,10 +1277,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:^18.16.0":
|
"@types/node@npm:^18.16.2":
|
||||||
version: 18.16.0
|
version: 18.16.2
|
||||||
resolution: "@types/node@npm:18.16.0"
|
resolution: "@types/node@npm:18.16.2"
|
||||||
checksum: 6e158e0e8a49f597f590f1d4c94a7b89b7ae707c0134540359559b14427e94dbde289c7557c8a2fe33baaaad478248a819fdccaa2b97a76dfa47bc61ab7f2ab6
|
checksum: ddcaecb88ffd85c9d6780d19839c40f00719d8159390225daed84a1c30cdbee50fe6ecef2f9c69010d07b7af3358bb800801f2f312fc985e8f183289eb32c6ad
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1285,12 +1298,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/react-dom@npm:^18.0.11":
|
"@types/react-dom@npm:^18.2.1":
|
||||||
version: 18.0.11
|
version: 18.2.1
|
||||||
resolution: "@types/react-dom@npm:18.0.11"
|
resolution: "@types/react-dom@npm:18.2.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
checksum: 8bf1e3f710221a937613df4d192f3b9e5a30e5c3103cac52c5210fb56b79f7a8cc66137d3bc5c9d92d375165a97fae53284724191bc01cb9898564fa02595569
|
checksum: 3af3c2a85f0f9fd96a03ce717559423cbd0bac3c8e279107008708d457db4b75a4ee7fd64d3af3ddad94cb97ff74dc422241edc56ab54f1905caca7fd717c759
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1344,14 +1357,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/react@npm:^18.0.38":
|
"@types/react@npm:^18.2.0":
|
||||||
version: 18.0.38
|
version: 18.2.0
|
||||||
resolution: "@types/react@npm:18.0.38"
|
resolution: "@types/react@npm:18.2.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types": "*"
|
"@types/prop-types": "*"
|
||||||
"@types/scheduler": "*"
|
"@types/scheduler": "*"
|
||||||
csstype: ^3.0.2
|
csstype: ^3.0.2
|
||||||
checksum: 39bad7b8ffe2288f7168fb35ce0fe12109771dcf985e673351074ca7ba8b67884686f92696692b90bbe28a68c2cfe3aabd691e717f88fbf19e01284a14abfdb5
|
checksum: e38f98b7524817459bb1214d39f4cfcb1dd7ffb31992a427b4494f3988aa6195dc349dfb66b299270b399b34568d045bf1cb6230349a6d343e183052ee486eaa
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1505,23 +1518,23 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "EMS-ESP@workspace:."
|
resolution: "EMS-ESP@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@emotion/react": ^11.10.6
|
"@emotion/react": ^11.10.8
|
||||||
"@emotion/styled": ^11.10.6
|
"@emotion/styled": ^11.10.8
|
||||||
"@msgpack/msgpack": ^3.0.0-beta2
|
"@msgpack/msgpack": ^3.0.0-beta2
|
||||||
"@mui/icons-material": ^5.11.16
|
"@mui/icons-material": ^5.11.16
|
||||||
"@mui/material": ^5.12.1
|
"@mui/material": ^5.12.2
|
||||||
"@remix-run/router": ^1.5.0
|
"@remix-run/router": ^1.5.0
|
||||||
"@table-library/react-table-library": 4.1.0
|
"@table-library/react-table-library": 4.1.2
|
||||||
"@types/lodash-es": ^4.17.7
|
"@types/lodash-es": ^4.17.7
|
||||||
"@types/node": ^18.16.0
|
"@types/node": ^18.16.2
|
||||||
"@types/react": ^18.0.38
|
"@types/react": ^18.2.0
|
||||||
"@types/react-dom": ^18.0.11
|
"@types/react-dom": ^18.2.1
|
||||||
"@types/react-router-dom": ^5.3.3
|
"@types/react-router-dom": ^5.3.3
|
||||||
"@typescript-eslint/eslint-plugin": ^5.59.1
|
"@typescript-eslint/eslint-plugin": ^5.59.1
|
||||||
"@typescript-eslint/parser": ^5.59.1
|
"@typescript-eslint/parser": ^5.59.1
|
||||||
"@vitejs/plugin-react-swc": ^3.3.0
|
"@vitejs/plugin-react-swc": ^3.3.0
|
||||||
async-validator: ^4.2.5
|
async-validator: ^4.2.5
|
||||||
axios: ^1.3.6
|
axios: ^1.4.0
|
||||||
eslint: ^8.39.0
|
eslint: ^8.39.0
|
||||||
eslint-config-airbnb: ^19.0.4
|
eslint-config-airbnb: ^19.0.4
|
||||||
eslint-config-airbnb-typescript: ^17.0.0
|
eslint-config-airbnb-typescript: ^17.0.0
|
||||||
@@ -1550,7 +1563,7 @@ __metadata:
|
|||||||
terser: ^5.17.1
|
terser: ^5.17.1
|
||||||
typesafe-i18n: ^5.24.3
|
typesafe-i18n: ^5.24.3
|
||||||
typescript: ^5.0.4
|
typescript: ^5.0.4
|
||||||
vite: ^4.3.1
|
vite: ^4.3.3
|
||||||
vite-plugin-svgr: ^2.4.0
|
vite-plugin-svgr: ^2.4.0
|
||||||
vite-tsconfig-paths: ^4.2.0
|
vite-tsconfig-paths: ^4.2.0
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
@@ -1800,14 +1813,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"axios@npm:^1.3.6":
|
"axios@npm:^1.4.0":
|
||||||
version: 1.3.6
|
version: 1.4.0
|
||||||
resolution: "axios@npm:1.3.6"
|
resolution: "axios@npm:1.4.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: ^1.15.0
|
follow-redirects: ^1.15.0
|
||||||
form-data: ^4.0.0
|
form-data: ^4.0.0
|
||||||
proxy-from-env: ^1.1.0
|
proxy-from-env: ^1.1.0
|
||||||
checksum: 451d7ec576a74b2846978e193458466f17ab676f1976630290e717e96aff84c90f755612d268731f722d363e45993e1844ef4fe8cdd022fe5663fc8f6267a7e3
|
checksum: a925a07590b0ec1d4daf28cd27890f930daab980371558deb3b883af174b881da09e5ba2cb8393a648fda5859e39934982d0b8b092fe89fc84cb6c80a70a1910
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -4190,7 +4203,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"nanoid@npm:^3.3.4":
|
"nanoid@npm:^3.3.6":
|
||||||
version: 3.3.6
|
version: 3.3.6
|
||||||
resolution: "nanoid@npm:3.3.6"
|
resolution: "nanoid@npm:3.3.6"
|
||||||
bin:
|
bin:
|
||||||
@@ -4607,14 +4620,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"postcss@npm:^8.4.21":
|
"postcss@npm:^8.4.23":
|
||||||
version: 8.4.21
|
version: 8.4.23
|
||||||
resolution: "postcss@npm:8.4.21"
|
resolution: "postcss@npm:8.4.23"
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid: ^3.3.4
|
nanoid: ^3.3.6
|
||||||
picocolors: ^1.0.0
|
picocolors: ^1.0.0
|
||||||
source-map-js: ^1.0.2
|
source-map-js: ^1.0.2
|
||||||
checksum: a26e7cc86a1807d624d9965914c26c20faa3f237184cbd69db537387f6a4f62df97347549144284d47e9e8e27e7c60e797cb3b92ad36cb2f4c3c9cb3b73f9758
|
checksum: 35c2e26496be286a63706a0b8240fc4d2075a746466df530989208f60ea33cbc80c89420221cffb7d4fdd605afc385993f5f60302447e3047a7c0a8756b6471d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -4989,9 +5002,9 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"rollup@npm:^3.20.2":
|
"rollup@npm:^3.21.0":
|
||||||
version: 3.20.6
|
version: 3.21.0
|
||||||
resolution: "rollup@npm:3.20.6"
|
resolution: "rollup@npm:3.21.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
fsevents: ~2.3.2
|
fsevents: ~2.3.2
|
||||||
dependenciesMeta:
|
dependenciesMeta:
|
||||||
@@ -4999,7 +5012,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
rollup: dist/bin/rollup
|
rollup: dist/bin/rollup
|
||||||
checksum: 977b4e3177dfca46d9b3f78d661a19a8da17543f11f154b6df0f45494794cf4203cbebeafd89b43bde1e99766c0fad35429cd13e3ee26d75d548166f7780154f
|
checksum: d88fdc7ea41e1db44b903575782bd7075886e158b31d9869505a06f7afa72ff17f9c6030973736c93142904ad1a9ee730724063a2df227740e587ec62aa4cde3
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -5413,6 +5426,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"stylis@npm:4.1.4":
|
||||||
|
version: 4.1.4
|
||||||
|
resolution: "stylis@npm:4.1.4"
|
||||||
|
checksum: 4f7f1ce3a13230315bdecbfbcfbc243c6e1b774f94b147005e396aa5e337fda668da78b0d666a5be51b3fcc096a3af3fc34cbdfd55b1bf92a66be654a5fe3fd8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"supports-color@npm:^5.3.0, supports-color@npm:^5.5.0":
|
"supports-color@npm:^5.3.0, supports-color@npm:^5.5.0":
|
||||||
version: 5.5.0
|
version: 5.5.0
|
||||||
resolution: "supports-color@npm:5.5.0"
|
resolution: "supports-color@npm:5.5.0"
|
||||||
@@ -5748,14 +5768,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"vite@npm:^4.3.1":
|
"vite@npm:^4.3.3":
|
||||||
version: 4.3.1
|
version: 4.3.3
|
||||||
resolution: "vite@npm:4.3.1"
|
resolution: "vite@npm:4.3.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: ^0.17.5
|
esbuild: ^0.17.5
|
||||||
fsevents: ~2.3.2
|
fsevents: ~2.3.2
|
||||||
postcss: ^8.4.21
|
postcss: ^8.4.23
|
||||||
rollup: ^3.20.2
|
rollup: ^3.21.0
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@types/node": ">= 14"
|
"@types/node": ">= 14"
|
||||||
less: "*"
|
less: "*"
|
||||||
@@ -5781,7 +5801,7 @@ __metadata:
|
|||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
vite: bin/vite.js
|
vite: bin/vite.js
|
||||||
checksum: c9a9ccb0405b2d76c228b989d283a03962d00d2f48491b8b8492162fe7b1f130e77f842970badb691e669ea75e3a137e417ffeeeab0e6944179d71cbd74fa166
|
checksum: 87814f40a1e21fb372014fe43d0faf3b8f166ee0bc458527b6bccd1b6340782f8e6f5a8986492d99bd31d02f7d1b1538cc0006a0ab6f7e311e603fd1782ae04e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
@@ -314,9 +314,9 @@ const EMSESP_DEVICEDATA_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceData';
|
|||||||
const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities';
|
const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities';
|
||||||
const EMSESP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'status';
|
const EMSESP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'status';
|
||||||
const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile';
|
const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile';
|
||||||
const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue';
|
const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue';
|
||||||
const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeSensor';
|
const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor';
|
||||||
const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalog';
|
const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalogSensor';
|
||||||
const EMSESP_CUSTOM_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities';
|
const EMSESP_CUSTOM_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities';
|
||||||
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations';
|
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations';
|
||||||
const EMSESP_WRITE_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
|
const EMSESP_WRITE_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
|
||||||
@@ -419,27 +419,25 @@ const emsesp_coredata = {
|
|||||||
v: '04.01',
|
v: '04.01',
|
||||||
e: 3
|
e: 3
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
s_n: 'Sensors',
|
|
||||||
active_sensors: 8,
|
|
||||||
analog_enabled: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const emsesp_sensordata = {
|
const emsesp_sensordata = {
|
||||||
sensors: [
|
// ts: [],
|
||||||
|
ts: [
|
||||||
{ id: '28-233D-9497-0C03', n: 'Dallas 1', t: 25.7, o: 1.2, u: 1 },
|
{ id: '28-233D-9497-0C03', n: 'Dallas 1', t: 25.7, o: 1.2, u: 1 },
|
||||||
{ id: '28-243D-7437-1E3A', n: 'Dallas 2 outside', t: 26.1, o: 0, u: 1 },
|
{ id: '28-243D-7437-1E3A', n: 'Dallas 2 outside', t: 26.1, o: 0, u: 1 },
|
||||||
{ id: '28-243E-7437-1E3B', n: 'Zolder', t: 27.1, o: 0, u: 16 },
|
{ id: '28-243E-7437-1E3B', n: 'Zolder', t: 27.1, o: 0, u: 16 },
|
||||||
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1 }
|
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1 }
|
||||||
],
|
],
|
||||||
// sensors: [],
|
// as: [],
|
||||||
analogs: [
|
as: [
|
||||||
{ id: '1', g: 36, n: 'motor', v: 0, u: 0, o: 17, f: 0, t: 0 },
|
{ id: 1, g: 36, n: 'motor', v: 0, u: 0, o: 17, f: 0, t: 0, d: false },
|
||||||
{ id: '2', g: 37, n: 'External switch', v: 13, u: 0, o: 17, f: 0, t: 1 },
|
{ id: 2, g: 37, n: 'External switch', v: 13, u: 0, o: 17, f: 0, t: 1, d: false },
|
||||||
{ id: '3', g: 39, n: 'Pulse count', v: 144, u: 0, o: 0, f: 0, t: 2 },
|
{ id: 3, g: 39, n: 'Pulse count', v: 144, u: 0, o: 0, f: 0, t: 2, d: false },
|
||||||
{ id: '4', g: 40, n: 'Pressure', v: 16, u: 17, o: 0, f: 0, t: 3 }
|
{ id: 4, g: 40, n: 'Pressure', v: 16, u: 17, o: 0, f: 0, t: 3, d: false }
|
||||||
]
|
],
|
||||||
// analogs: [],
|
analog_enabled: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const status = {
|
const status = {
|
||||||
@@ -965,6 +963,7 @@ rest_server.get(EMSESP_CORE_DATA_ENDPOINT, (req, res) => {
|
|||||||
});
|
});
|
||||||
rest_server.get(EMSESP_SENSOR_DATA_ENDPOINT, (req, res) => {
|
rest_server.get(EMSESP_SENSOR_DATA_ENDPOINT, (req, res) => {
|
||||||
console.log('send back sensor data...');
|
console.log('send back sensor data...');
|
||||||
|
console.log(emsesp_sensordata);
|
||||||
res.json(emsesp_sensordata);
|
res.json(emsesp_sensordata);
|
||||||
});
|
});
|
||||||
rest_server.get(EMSESP_DEVICES_ENDPOINT, (req, res) => {
|
rest_server.get(EMSESP_DEVICES_ENDPOINT, (req, res) => {
|
||||||
@@ -1154,12 +1153,12 @@ rest_server.post(EMSESP_WRITE_VALUE_ENDPOINT, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rest_server.post(EMSESP_WRITE_SENSOR_ENDPOINT, (req, res) => {
|
rest_server.post(EMSESP_WRITE_SENSOR_ENDPOINT, (req, res) => {
|
||||||
const sensor = req.body;
|
const ts = req.body;
|
||||||
console.log('Write sensor: ' + JSON.stringify(sensor));
|
console.log('Write temperaure sensor: ' + JSON.stringify(ts));
|
||||||
objIndex = emsesp_sensordata.sensors.findIndex((obj) => obj.id == sensor.id);
|
objIndex = emsesp_sensordata.ts.findIndex((obj) => obj.id == ts.id);
|
||||||
if (objIndex !== -1) {
|
if (objIndex !== -1) {
|
||||||
emsesp_sensordata.sensors[objIndex].n = sensor.name;
|
emsesp_sensordata.ts[objIndex].n = ts.name;
|
||||||
emsesp_sensordata.sensors[objIndex].o = sensor.offset;
|
emsesp_sensordata.ts[objIndex].o = ts.offset;
|
||||||
} else {
|
} else {
|
||||||
console.log('not found');
|
console.log('not found');
|
||||||
}
|
}
|
||||||
@@ -1167,32 +1166,37 @@ rest_server.post(EMSESP_WRITE_SENSOR_ENDPOINT, (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
rest_server.post(EMSESP_WRITE_ANALOG_ENDPOINT, (req, res) => {
|
rest_server.post(EMSESP_WRITE_ANALOG_ENDPOINT, (req, res) => {
|
||||||
const analog = req.body;
|
const as = req.body;
|
||||||
console.log('Write analog: ' + JSON.stringify(analog));
|
console.log('Write analog sensor: ' + JSON.stringify(as));
|
||||||
objIndex = emsesp_sensordata.analogs.findIndex((obj) => obj.g == analog.gpio);
|
objIndex = emsesp_sensordata.as.findIndex((obj) => obj.g == as.gpio);
|
||||||
|
|
||||||
if (objIndex === -1) {
|
if (objIndex === -1) {
|
||||||
console.log('new analog');
|
console.log('new analog entry found');
|
||||||
emsesp_sensordata.analogs.push({
|
emsesp_sensordata.as.push({
|
||||||
id: analog.i.toString(),
|
id: as.id,
|
||||||
g: analog.gpio,
|
g: as.gpio,
|
||||||
n: analog.name,
|
n: as.name,
|
||||||
f: analog.factor,
|
f: as.factor,
|
||||||
o: analog.offset,
|
o: as.offset,
|
||||||
u: analog.uom,
|
u: as.uom,
|
||||||
t: analog.type
|
t: as.type,
|
||||||
|
d: as.deleted
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (analog.type === -1) {
|
if (as.deleted) {
|
||||||
console.log('removing analog gpio' + analog.gpio + ' index ' + objIndex);
|
console.log('removing analog gpio' + as.gpio + ' index ' + objIndex);
|
||||||
emsesp_sensordata.analogs[objIndex].t = -1;
|
emsesp_sensordata.as[objIndex].d = true;
|
||||||
|
var filtered = emsesp_sensordata.as.filter(function (value, index, arr) {
|
||||||
|
return !value.d;
|
||||||
|
});
|
||||||
|
emsesp_sensordata.as = filtered;
|
||||||
} else {
|
} else {
|
||||||
console.log('updating analog gpio' + analog.gpio + ' index ' + objIndex);
|
console.log('updating analog gpio' + as.gpio + ' index ' + objIndex);
|
||||||
emsesp_sensordata.analogs[objIndex].n = analog.name;
|
emsesp_sensordata.as[objIndex].n = as.name;
|
||||||
emsesp_sensordata.analogs[objIndex].f = analog.factor;
|
emsesp_sensordata.as[objIndex].f = as.factor;
|
||||||
emsesp_sensordata.analogs[objIndex].o = analog.offset;
|
emsesp_sensordata.as[objIndex].o = as.offset;
|
||||||
emsesp_sensordata.analogs[objIndex].u = analog.uom;
|
emsesp_sensordata.as[objIndex].u = as.uom;
|
||||||
emsesp_sensordata.analogs[objIndex].t = analog.type;
|
emsesp_sensordata.as[objIndex].t = as.type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1339,7 +1343,7 @@ const emsesp_info = {
|
|||||||
'uptime (seconds)': 110434,
|
'uptime (seconds)': 110434,
|
||||||
freemem: 131,
|
freemem: 131,
|
||||||
'reset reason': 'Software reset CPU / Software reset CPU',
|
'reset reason': 'Software reset CPU / Software reset CPU',
|
||||||
'Dallas sensors': 3
|
'Sensor sensors': 3
|
||||||
},
|
},
|
||||||
Network: {
|
Network: {
|
||||||
connection: 'Ethernet',
|
connection: 'Ethernet',
|
||||||
@@ -1362,8 +1366,8 @@ const emsesp_info = {
|
|||||||
MQTT: 'connected',
|
MQTT: 'connected',
|
||||||
'MQTT publishes': 46336,
|
'MQTT publishes': 46336,
|
||||||
'MQTT publish fails': 0,
|
'MQTT publish fails': 0,
|
||||||
'Dallas reads': 22086,
|
'Sensor reads': 22086,
|
||||||
'Dallas fails': 0
|
'Sensor fails': 0
|
||||||
},
|
},
|
||||||
Devices: [
|
Devices: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
; -DEMSESP_UART_DEBUG ; debugging UART
|
; -DEMSESP_UART_DEBUG ; debugging UART
|
||||||
; -DEMSESP_DEBUG ; enables DEBUG to the log. Will generate a lot of extra traffic on Console and Syslog
|
; -DEMSESP_DEBUG ; enables DEBUG to the log. Will generate a lot of extra traffic on Console and Syslog
|
||||||
; -DEMSESP_DEFAULT_BOARD_PROFILE=\"NODEMCU\" ; hard code the default board name
|
; -DEMSESP_DEFAULT_BOARD_PROFILE=\"NODEMCU\" ; hard code the default board name
|
||||||
; -DEMSESP_DEBUG_SENSOR ; additional debug for the dallas sensors
|
; -DEMSESP_DEBUG_SENSOR ; additional debug for the sensors
|
||||||
; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info
|
; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info
|
||||||
; -DEMSESP_TEST ; enable the tests. EN language only
|
; -DEMSESP_TEST ; enable the tests. EN language only
|
||||||
; -DEMSESP_DE_ONLY ; only DE translated entity names
|
; -DEMSESP_DE_ONLY ; only DE translated entity names
|
||||||
|
|||||||
@@ -301,7 +301,8 @@ void AnalogSensor::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update analog information name and offset
|
// update analog information name and offset
|
||||||
bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type) {
|
// a type of -1 is used to delete the sensor
|
||||||
|
bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted) {
|
||||||
boolean found_sensor = false; // see if we can find the sensor in our customization list
|
boolean found_sensor = false; // see if we can find the sensor in our customization list
|
||||||
|
|
||||||
EMSESP::webCustomizationService.update(
|
EMSESP::webCustomizationService.update(
|
||||||
@@ -313,7 +314,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset,
|
|||||||
if (AnalogCustomization.gpio == gpio) {
|
if (AnalogCustomization.gpio == gpio) {
|
||||||
found_sensor = true; // found the record
|
found_sensor = true; // found the record
|
||||||
// see if it's marked for deletion
|
// see if it's marked for deletion
|
||||||
if (type == AnalogType::MARK_DELETED) {
|
if (deleted) {
|
||||||
LOG_DEBUG("Removing analog sensor GPIO %02d", gpio);
|
LOG_DEBUG("Removing analog sensor GPIO %02d", gpio);
|
||||||
settings.analogCustomizations.remove(AnalogCustomization);
|
settings.analogCustomizations.remove(AnalogCustomization);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ class AnalogSensor {
|
|||||||
~AnalogSensor() = default;
|
~AnalogSensor() = default;
|
||||||
|
|
||||||
enum AnalogType : int8_t {
|
enum AnalogType : int8_t {
|
||||||
MARK_DELETED = -1, // mark for deletion
|
NOTUSED, // 0 - disabled
|
||||||
NOTUSED, // 0 - disabled
|
|
||||||
DIGITAL_IN,
|
DIGITAL_IN,
|
||||||
COUNTER,
|
COUNTER,
|
||||||
ADC,
|
ADC,
|
||||||
@@ -157,7 +156,7 @@ class AnalogSensor {
|
|||||||
return sensors_.size();
|
return sensors_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type);
|
bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false);
|
||||||
bool get_value_info(JsonObject & output, const char * cmd, const int8_t id) const;
|
bool get_value_info(JsonObject & output, const char * cmd, const int8_t id) const;
|
||||||
|
|
||||||
#if defined(EMSESP_TEST)
|
#if defined(EMSESP_TEST)
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ void Command::add(const uint8_t device_type, const uint8_t device_id, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add a command with no json output
|
// add a command with no json output
|
||||||
// system/dallas/analog devices uses device_id 0
|
// system/temperature/analog devices uses device_id 0
|
||||||
void Command::add(const uint8_t device_type, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
void Command::add(const uint8_t device_type, const char * cmd, const cmd_function_p cb, const char * const * description, uint8_t flags) {
|
||||||
add(device_type, 0, cmd, cb, description, flags);
|
add(device_type, 0, cmd, cb, description, flags);
|
||||||
}
|
}
|
||||||
@@ -543,8 +543,8 @@ bool Command::device_has_commands(const uint8_t device_type) {
|
|||||||
return (EMSESP::webEntityService.count_entities() != 0);
|
return (EMSESP::webEntityService.count_entities() != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_type == EMSdevice::DeviceType::DALLASSENSOR) {
|
if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) {
|
||||||
return (EMSESP::dallassensor_.have_sensors());
|
return (EMSESP::temperaturesensor_.have_sensors());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_type == EMSdevice::DeviceType::ANALOGSENSOR) {
|
if (device_type == EMSdevice::DeviceType::ANALOGSENSOR) {
|
||||||
@@ -572,8 +572,8 @@ void Command::show_devices(uuid::console::Shell & shell) {
|
|||||||
if (EMSESP::webSchedulerService.has_commands()) {
|
if (EMSESP::webSchedulerService.has_commands()) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER));
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER));
|
||||||
}
|
}
|
||||||
if (EMSESP::dallassensor_.have_sensors()) {
|
if (EMSESP::temperaturesensor_.have_sensors()) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR));
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
|
||||||
}
|
}
|
||||||
if (EMSESP::analogsensor_.have_sensors()) {
|
if (EMSESP::analogsensor_.have_sensors()) {
|
||||||
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
shell.printf("%s ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
||||||
@@ -616,12 +616,12 @@ void Command::show_all(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show sensors
|
// show sensors
|
||||||
if (EMSESP::dallassensor_.have_sensors()) {
|
if (EMSESP::temperaturesensor_.have_sensors()) {
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
shell.print(COLOR_YELLOW);
|
shell.print(COLOR_YELLOW);
|
||||||
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR));
|
shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
|
||||||
shell.print(COLOR_RESET);
|
shell.print(COLOR_RESET);
|
||||||
show(shell, EMSdevice::DeviceType::DALLASSENSOR, true);
|
show(shell, EMSdevice::DeviceType::TEMPERATURESENSOR, true);
|
||||||
}
|
}
|
||||||
if (EMSESP::analogsensor_.have_sensors()) {
|
if (EMSESP::analogsensor_.have_sensors()) {
|
||||||
shell.print(COLOR_BOLD_ON);
|
shell.print(COLOR_BOLD_ON);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class Command {
|
|||||||
const char * const * description,
|
const char * const * description,
|
||||||
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
uint8_t flags = CommandFlag::MQTT_SUB_FLAG_DEFAULT);
|
||||||
|
|
||||||
// same for system/dallas/analog devices
|
// same for system/temperature/analog devices
|
||||||
static void add(const uint8_t device_type,
|
static void add(const uint8_t device_type,
|
||||||
const char * cmd,
|
const char * cmd,
|
||||||
const cmd_function_p cb,
|
const cmd_function_p cb,
|
||||||
|
|||||||
@@ -569,7 +569,7 @@ static void setup_commands(std::shared_ptr<Commands> & commands) {
|
|||||||
if (current_arguments.size() == 0) {
|
if (current_arguments.size() == 0) {
|
||||||
std::vector<std::string> devices_list;
|
std::vector<std::string> devices_list;
|
||||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM));
|
||||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::DALLASSENSOR));
|
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR));
|
||||||
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
devices_list.emplace_back(EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR));
|
||||||
for (const auto & device_class : EMSFactory::device_handlers()) {
|
for (const auto & device_class : EMSFactory::device_handlers()) {
|
||||||
if (Command::device_has_commands(device_class.first)) {
|
if (Command::device_has_commands(device_class.first)) {
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
|||||||
return F_(connect);
|
return F_(connect);
|
||||||
case DeviceType::MIXER:
|
case DeviceType::MIXER:
|
||||||
return F_(mixer);
|
return F_(mixer);
|
||||||
case DeviceType::DALLASSENSOR:
|
case DeviceType::TEMPERATURESENSOR:
|
||||||
return F_(dallassensor);
|
return F_(temperaturesensor);
|
||||||
case DeviceType::ANALOGSENSOR:
|
case DeviceType::ANALOGSENSOR:
|
||||||
return F_(analogsensor);
|
return F_(analogsensor);
|
||||||
case DeviceType::CONTROLLER:
|
case DeviceType::CONTROLLER:
|
||||||
@@ -143,7 +143,7 @@ const char * EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns the translated name of a specific EMS device
|
// returns the translated name of a specific EMS device
|
||||||
// excludes dallassensor, analogsensor and system
|
// excludes temperaturesensor, analogsensor and system
|
||||||
const char * EMSdevice::device_type_2_device_name_translated() {
|
const char * EMSdevice::device_type_2_device_name_translated() {
|
||||||
switch (device_type_) {
|
switch (device_type_) {
|
||||||
case DeviceType::BOILER:
|
case DeviceType::BOILER:
|
||||||
@@ -210,8 +210,8 @@ uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
|
|||||||
if (!strcmp(lowtopic, F_(mixer))) {
|
if (!strcmp(lowtopic, F_(mixer))) {
|
||||||
return DeviceType::MIXER;
|
return DeviceType::MIXER;
|
||||||
}
|
}
|
||||||
if (!strcmp(lowtopic, F_(dallassensor))) {
|
if (!strcmp(lowtopic, F_(temperaturesensor))) {
|
||||||
return DeviceType::DALLASSENSOR;
|
return DeviceType::TEMPERATURESENSOR;
|
||||||
}
|
}
|
||||||
if (!strcmp(lowtopic, F_(analogsensor))) {
|
if (!strcmp(lowtopic, F_(analogsensor))) {
|
||||||
return DeviceType::ANALOGSENSOR;
|
return DeviceType::ANALOGSENSOR;
|
||||||
|
|||||||
@@ -319,9 +319,9 @@ class EMSdevice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum DeviceType : uint8_t {
|
enum DeviceType : uint8_t {
|
||||||
SYSTEM = 0, // this is us (EMS-ESP)
|
SYSTEM = 0, // this is us (EMS-ESP)
|
||||||
DALLASSENSOR, // for internal dallas sensors
|
TEMPERATURESENSOR, // for internal temperature sensors
|
||||||
ANALOGSENSOR, // for internal analog sensors
|
ANALOGSENSOR, // for internal analog sensors
|
||||||
SCHEDULER,
|
SCHEDULER,
|
||||||
BOILER,
|
BOILER,
|
||||||
THERMOSTAT,
|
THERMOSTAT,
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ uuid::syslog::SyslogService System::syslog_;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The services
|
// The services
|
||||||
RxService EMSESP::rxservice_; // incoming Telegram Rx handler
|
RxService EMSESP::rxservice_; // incoming Telegram Rx handler
|
||||||
TxService EMSESP::txservice_; // outgoing Telegram Tx handler
|
TxService EMSESP::txservice_; // outgoing Telegram Tx handler
|
||||||
Mqtt EMSESP::mqtt_; // mqtt handler
|
Mqtt EMSESP::mqtt_; // mqtt handler
|
||||||
System EMSESP::system_; // core system services
|
System EMSESP::system_; // core system services
|
||||||
DallasSensor EMSESP::dallassensor_; // Dallas sensors
|
TemperatureSensor EMSESP::temperaturesensor_; // Temperature sensors
|
||||||
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
||||||
Shower EMSESP::shower_; // Shower logic
|
Shower EMSESP::shower_; // Shower logic
|
||||||
|
|
||||||
// static/common variables
|
// static/common variables
|
||||||
uint16_t EMSESP::watch_id_ = WATCH_ID_NONE; // for when log is TRACE. 0 means no trace set
|
uint16_t EMSESP::watch_id_ = WATCH_ID_NONE; // for when log is TRACE. 0 means no trace set
|
||||||
@@ -408,15 +408,15 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// show Dallas temperature sensors and Analog sensors
|
// show temperature sensors and Analog sensors
|
||||||
void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
void EMSESP::show_sensor_values(uuid::console::Shell & shell) {
|
||||||
if (dallassensor_.have_sensors()) {
|
if (temperaturesensor_.have_sensors()) {
|
||||||
shell.printfln("Temperature sensors:");
|
shell.printfln("Temperature sensors:");
|
||||||
char s[10];
|
char s[10];
|
||||||
char s2[10];
|
char s2[10];
|
||||||
uint8_t fahrenheit = EMSESP::system_.fahrenheit() ? 2 : 0;
|
uint8_t fahrenheit = EMSESP::system_.fahrenheit() ? 2 : 0;
|
||||||
|
|
||||||
for (const auto & sensor : dallassensor_.sensors()) {
|
for (const auto & sensor : temperaturesensor_.sensors()) {
|
||||||
if (Helpers::hasValue(sensor.temperature_c)) {
|
if (Helpers::hasValue(sensor.temperature_c)) {
|
||||||
shell.printfln(" %s: %s%s °%c%s (offset %s, ID: %s)",
|
shell.printfln(" %s: %s%s °%c%s (offset %s, ID: %s)",
|
||||||
sensor.name().c_str(),
|
sensor.name().c_str(),
|
||||||
@@ -481,7 +481,7 @@ void EMSESP::publish_all(bool force) {
|
|||||||
publish_other_values(); // switch and heat pump, ...
|
publish_other_values(); // switch and heat pump, ...
|
||||||
webSchedulerService.publish();
|
webSchedulerService.publish();
|
||||||
webEntityService.publish();
|
webEntityService.publish();
|
||||||
publish_sensor_values(true); // includes dallas and analog sensors
|
publish_sensor_values(true); // includes temperature and analog sensors
|
||||||
system_.send_heartbeat();
|
system_.send_heartbeat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,8 +541,8 @@ void EMSESP::reset_mqtt_ha() {
|
|||||||
emsdevice->ha_config_clear();
|
emsdevice->ha_config_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// force the re-creating of the dallas and analog sensor topics (for HA)
|
// force the re-creating of the temperature and analog sensor topics (for HA)
|
||||||
dallassensor_.reload();
|
temperaturesensor_.reload();
|
||||||
analogsensor_.reload();
|
analogsensor_.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,11 +606,11 @@ void EMSESP::publish_other_values() {
|
|||||||
webEntityService.publish();
|
webEntityService.publish();
|
||||||
}
|
}
|
||||||
|
|
||||||
// publish both the dallas and analog sensor values
|
// publish both the temperature and analog sensor values
|
||||||
void EMSESP::publish_sensor_values(const bool time, const bool force) {
|
void EMSESP::publish_sensor_values(const bool time, const bool force) {
|
||||||
if (dallas_enabled()) {
|
if (sensor_enabled()) {
|
||||||
if (dallassensor_.updated_values() || time || force) {
|
if (temperaturesensor_.updated_values() || time || force) {
|
||||||
dallassensor_.publish_values(force);
|
temperaturesensor_.publish_values(force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,7 +644,7 @@ void EMSESP::publish_response(std::shared_ptr<const Telegram> telegram) {
|
|||||||
Mqtt::queue_publish("response", doc.as<JsonObject>());
|
Mqtt::queue_publish("response", doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// builds json with the detail of each value, for a specific EMS device type or the dallas sensor
|
// builds json with the detail of each value, for a specific EMS device type or the temperature sensor
|
||||||
bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) {
|
bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype) {
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice->device_type() == devicetype) {
|
if (emsdevice->device_type() == devicetype) {
|
||||||
@@ -654,9 +654,9 @@ bool EMSESP::get_device_value_info(JsonObject & root, const char * cmd, const in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// specific for the dallassensor
|
// specific for the temperaturesensor
|
||||||
if (devicetype == DeviceType::DALLASSENSOR) {
|
if (devicetype == DeviceType::TEMPERATURESENSOR) {
|
||||||
return EMSESP::dallassensor_.get_value_info(root, cmd, id);
|
return EMSESP::temperaturesensor_.get_value_info(root, cmd, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// analog sensor
|
// analog sensor
|
||||||
@@ -1489,10 +1489,10 @@ void EMSESP::start() {
|
|||||||
|
|
||||||
LOG_INFO(("Starting EMS-ESP version %s (hostname: %s)"), EMSESP_APP_VERSION, system_.hostname().c_str()); // welcome message
|
LOG_INFO(("Starting EMS-ESP version %s (hostname: %s)"), EMSESP_APP_VERSION, system_.hostname().c_str()); // welcome message
|
||||||
|
|
||||||
shower_.start(); // initialize shower timer and shower alert
|
shower_.start(); // initialize shower timer and shower alert
|
||||||
dallassensor_.start(); // Dallas external sensors
|
temperaturesensor_.start(); // Temperature external sensors
|
||||||
analogsensor_.start(); // Analog external sensors
|
analogsensor_.start(); // Analog external sensors
|
||||||
webLogService.start(); // apply settings to weblog service
|
webLogService.start(); // apply settings to weblog service
|
||||||
|
|
||||||
// Load our library of known devices into stack mem. Names are stored in Flash memory
|
// Load our library of known devices into stack mem. Names are stored in Flash memory
|
||||||
device_library_ = {
|
device_library_ = {
|
||||||
@@ -1518,7 +1518,7 @@ void EMSESP::loop() {
|
|||||||
webLogService.loop(); // log in Web UI
|
webLogService.loop(); // log in Web UI
|
||||||
rxservice_.loop(); // process any incoming Rx telegrams
|
rxservice_.loop(); // process any incoming Rx telegrams
|
||||||
shower_.loop(); // check for shower on/off
|
shower_.loop(); // check for shower on/off
|
||||||
dallassensor_.loop(); // read dallas sensor temperatures
|
temperaturesensor_.loop(); // read sensor temperatures
|
||||||
analogsensor_.loop(); // read analog sensor values
|
analogsensor_.loop(); // read analog sensor values
|
||||||
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
||||||
mqtt_.loop(); // sends out anything in the MQTT queue
|
mqtt_.loop(); // sends out anything in the MQTT queue
|
||||||
|
|||||||
20
src/emsesp.h
20
src/emsesp.h
@@ -54,7 +54,7 @@
|
|||||||
#include "telegram.h"
|
#include "telegram.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "dallassensor.h"
|
#include "temperaturesensor.h"
|
||||||
#include "analogsensor.h"
|
#include "analogsensor.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "console_stream.h"
|
#include "console_stream.h"
|
||||||
@@ -148,8 +148,8 @@ class EMSESP {
|
|||||||
|
|
||||||
static void incoming_telegram(uint8_t * data, const uint8_t length);
|
static void incoming_telegram(uint8_t * data, const uint8_t length);
|
||||||
|
|
||||||
static bool dallas_enabled() {
|
static bool sensor_enabled() {
|
||||||
return (dallassensor_.dallas_enabled());
|
return (temperaturesensor_.sensor_enabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool analog_enabled() {
|
static bool analog_enabled() {
|
||||||
@@ -214,13 +214,13 @@ class EMSESP {
|
|||||||
static std::vector<std::unique_ptr<EMSdevice>> emsdevices;
|
static std::vector<std::unique_ptr<EMSdevice>> emsdevices;
|
||||||
|
|
||||||
// services
|
// services
|
||||||
static Mqtt mqtt_;
|
static Mqtt mqtt_;
|
||||||
static System system_;
|
static System system_;
|
||||||
static DallasSensor dallassensor_;
|
static TemperatureSensor temperaturesensor_;
|
||||||
static AnalogSensor analogsensor_;
|
static AnalogSensor analogsensor_;
|
||||||
static Shower shower_;
|
static Shower shower_;
|
||||||
static RxService rxservice_;
|
static RxService rxservice_;
|
||||||
static TxService txservice_;
|
static TxService txservice_;
|
||||||
|
|
||||||
// web controllers
|
// web controllers
|
||||||
static ESP8266React esp8266React;
|
static ESP8266React esp8266React;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
#include "dallassensor.h"
|
#include "temperaturesensor.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "default_settings.h"
|
#include "default_settings.h"
|
||||||
|
|
||||||
@@ -33,9 +33,9 @@
|
|||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
class EMSESP {
|
class EMSESP {
|
||||||
public:
|
public:
|
||||||
static Mqtt mqtt_;
|
static Mqtt mqtt_;
|
||||||
static System system_;
|
static System system_;
|
||||||
static DallasSensor dallassensor_;
|
static TemperatureSensor temperaturesensor_;
|
||||||
|
|
||||||
static uuid::log::Logger logger();
|
static uuid::log::Logger logger();
|
||||||
static ESP8266React esp8266React;
|
static ESP8266React esp8266React;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ MAKE_WORD(connect)
|
|||||||
MAKE_WORD(heatpump)
|
MAKE_WORD(heatpump)
|
||||||
MAKE_WORD(generic)
|
MAKE_WORD(generic)
|
||||||
MAKE_WORD(analogsensor)
|
MAKE_WORD(analogsensor)
|
||||||
MAKE_WORD(dallassensor)
|
MAKE_WORD(temperaturesensor)
|
||||||
MAKE_WORD(alert)
|
MAKE_WORD(alert)
|
||||||
MAKE_WORD(pump)
|
MAKE_WORD(pump)
|
||||||
MAKE_WORD(heatsource)
|
MAKE_WORD(heatsource)
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ void Mqtt::loop() {
|
|||||||
EMSESP::system_.send_heartbeat(); // send heartbeat
|
EMSESP::system_.send_heartbeat(); // send heartbeat
|
||||||
}
|
}
|
||||||
|
|
||||||
// dallas publish on change
|
// temperature and analog sensor publish on change
|
||||||
if (!publish_time_sensor_) {
|
if (!publish_time_sensor_) {
|
||||||
EMSESP::publish_sensor_values(false);
|
EMSESP::publish_sensor_values(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ bool System::command_publish(const char * value, const int8_t id) {
|
|||||||
} else if (value_s == "other") {
|
} else if (value_s == "other") {
|
||||||
EMSESP::publish_other_values(); // switch and heat pump
|
EMSESP::publish_other_values(); // switch and heat pump
|
||||||
return true;
|
return true;
|
||||||
} else if ((value_s == (F_(dallassensor))) || (value_s == (F_(analogsensor)))) {
|
} else if ((value_s == (F_(temperaturesensor))) || (value_s == (F_(analogsensor)))) {
|
||||||
EMSESP::publish_sensor_values(true);
|
EMSESP::publish_sensor_values(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -611,9 +611,9 @@ bool System::heartbeat_json(JsonObject & output) {
|
|||||||
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
|
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
|
||||||
output["apifails"] = WebAPIService::api_fails();
|
output["apifails"] = WebAPIService::api_fails();
|
||||||
|
|
||||||
if (EMSESP::dallas_enabled() || EMSESP::analog_enabled()) {
|
if (EMSESP::sensor_enabled() || EMSESP::analog_enabled()) {
|
||||||
output["sensorreads"] = EMSESP::dallassensor_.reads() + EMSESP::analogsensor_.reads();
|
output["sensorreads"] = EMSESP::temperaturesensor_.reads() + EMSESP::analogsensor_.reads();
|
||||||
output["sensorfails"] = EMSESP::dallassensor_.fails() + EMSESP::analogsensor_.fails();
|
output["sensorfails"] = EMSESP::temperaturesensor_.fails() + EMSESP::analogsensor_.fails();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
@@ -1267,10 +1267,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
|||||||
|
|
||||||
// Sensor Status
|
// Sensor Status
|
||||||
node = output.createNestedObject("Sensor Info");
|
node = output.createNestedObject("Sensor Info");
|
||||||
if (EMSESP::dallas_enabled()) {
|
if (EMSESP::sensor_enabled()) {
|
||||||
node["temperature sensors"] = EMSESP::dallassensor_.no_sensors();
|
node["temperature sensors"] = EMSESP::temperaturesensor_.no_sensors();
|
||||||
node["temperature sensor reads"] = EMSESP::dallassensor_.reads();
|
node["temperature sensor reads"] = EMSESP::temperaturesensor_.reads();
|
||||||
node["temperature sensor fails"] = EMSESP::dallassensor_.fails();
|
node["temperature sensor fails"] = EMSESP::temperaturesensor_.fails();
|
||||||
}
|
}
|
||||||
if (EMSESP::analog_enabled()) {
|
if (EMSESP::analog_enabled()) {
|
||||||
node["analog sensors"] = EMSESP::analogsensor_.no_sensors();
|
node["analog sensors"] = EMSESP::analogsensor_.no_sensors();
|
||||||
@@ -1418,7 +1418,7 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
|
|||||||
} else if (board_profile == "LOLIN") {
|
} else if (board_profile == "LOLIN") {
|
||||||
data = {2, 18, 17, 16, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin D32
|
data = {2, 18, 17, 16, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin D32
|
||||||
} else if (board_profile == "OLIMEX") {
|
} else if (board_profile == "OLIMEX") {
|
||||||
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, -1, 0, 0}; // Olimex ESP32-EVB (uses U1TXD/U1RXD/BUTTON, no LED or Dallas)
|
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, -1, 0, 0}; // Olimex ESP32-EVB (uses U1TXD/U1RXD/BUTTON, no LED or Temperature sensor)
|
||||||
} else if (board_profile == "OLIMEXPOE") {
|
} else if (board_profile == "OLIMEXPOE") {
|
||||||
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE
|
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE
|
||||||
} else if (board_profile == "C3MINI") {
|
} else if (board_profile == "C3MINI") {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
// code originally written by nomis - https://github.com/nomis
|
// code originally written by nomis - https://github.com/nomis
|
||||||
|
|
||||||
#include "dallassensor.h"
|
#include "temperaturesensor.h"
|
||||||
#include "emsesp.h"
|
#include "emsesp.h"
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
@@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
uuid::log::Logger DallasSensor::logger_{F_(dallassensor), uuid::log::Facility::DAEMON};
|
uuid::log::Logger TemperatureSensor::logger_{F_(temperaturesensor), uuid::log::Facility::DAEMON};
|
||||||
|
|
||||||
// start the 1-wire
|
// start the 1-wire
|
||||||
void DallasSensor::start() {
|
void TemperatureSensor::start() {
|
||||||
reload();
|
reload();
|
||||||
|
|
||||||
if (!dallas_gpio_) {
|
if (!dallas_gpio_) {
|
||||||
@@ -42,32 +42,32 @@ void DallasSensor::start() {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
bus_.begin(dallas_gpio_);
|
bus_.begin(dallas_gpio_);
|
||||||
LOG_INFO("Starting Dallas sensor service");
|
LOG_INFO("Starting Temperature sensor service");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add API calls
|
// Add API calls
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::DALLASSENSOR,
|
EMSdevice::DeviceType::TEMPERATURESENSOR,
|
||||||
F_(info),
|
F_(info),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, id, output); },
|
||||||
FL_(info_cmd));
|
FL_(info_cmd));
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::DALLASSENSOR,
|
EMSdevice::DeviceType::TEMPERATURESENSOR,
|
||||||
F_(values),
|
F_(values),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, 0, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_info(value, 0, output); },
|
||||||
nullptr,
|
nullptr,
|
||||||
CommandFlag::HIDDEN); // this command is hidden
|
CommandFlag::HIDDEN); // this command is hidden
|
||||||
Command::add(
|
Command::add(
|
||||||
EMSdevice::DeviceType::DALLASSENSOR,
|
EMSdevice::DeviceType::TEMPERATURESENSOR,
|
||||||
F_(commands),
|
F_(commands),
|
||||||
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
[&](const char * value, const int8_t id, JsonObject & output) { return command_commands(value, id, output); },
|
||||||
FL_(commands_cmd));
|
FL_(commands_cmd));
|
||||||
|
|
||||||
Mqtt::subscribe(EMSdevice::DeviceType::DALLASSENSOR, "dallasssensor/#", nullptr); // use empty function callback
|
Mqtt::subscribe(EMSdevice::DeviceType::TEMPERATURESENSOR, "temperaturesensor/#", nullptr); // use empty function callback
|
||||||
}
|
}
|
||||||
|
|
||||||
// load settings
|
// load settings
|
||||||
void DallasSensor::reload() {
|
void TemperatureSensor::reload() {
|
||||||
// load the service settings
|
// load the service settings
|
||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||||
dallas_gpio_ = settings.dallas_gpio;
|
dallas_gpio_ = settings.dallas_gpio;
|
||||||
@@ -80,7 +80,7 @@ void DallasSensor::reload() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DallasSensor::loop() {
|
void TemperatureSensor::loop() {
|
||||||
if (!dallas_gpio_) {
|
if (!dallas_gpio_) {
|
||||||
return; // dallas gpio is 0 (disabled)
|
return; // dallas gpio is 0 (disabled)
|
||||||
}
|
}
|
||||||
@@ -119,13 +119,13 @@ void DallasSensor::loop() {
|
|||||||
} else if (state_ == State::READING) {
|
} else if (state_ == State::READING) {
|
||||||
if (temperature_convert_complete() && (time_now - last_activity_ > CONVERSION_MS)) {
|
if (temperature_convert_complete() && (time_now - last_activity_ > CONVERSION_MS)) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_DEBUG("Scanning for sensors");
|
LOG_DEBUG("Scanning for temperature sensors");
|
||||||
#endif
|
#endif
|
||||||
bus_.reset_search();
|
bus_.reset_search();
|
||||||
state_ = State::SCANNING;
|
state_ = State::SCANNING;
|
||||||
} else if (time_now - last_activity_ > READ_TIMEOUT_MS) {
|
} else if (time_now - last_activity_ > READ_TIMEOUT_MS) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_WARNING("Dallas sensor read timeout");
|
LOG_WARNING("Sensor read timeout");
|
||||||
#endif
|
#endif
|
||||||
state_ = State::IDLE;
|
state_ = State::IDLE;
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
@@ -133,7 +133,7 @@ void DallasSensor::loop() {
|
|||||||
} else if (state_ == State::SCANNING) {
|
} else if (state_ == State::SCANNING) {
|
||||||
if (time_now - last_activity_ > SCAN_TIMEOUT_MS) {
|
if (time_now - last_activity_ > SCAN_TIMEOUT_MS) {
|
||||||
#ifdef EMSESP_DEBUG_SENSOR
|
#ifdef EMSESP_DEBUG_SENSOR
|
||||||
LOG_ERROR("Dallas sensor scan timeout");
|
LOG_ERROR("Sensor scan timeout");
|
||||||
#endif
|
#endif
|
||||||
state_ = State::IDLE;
|
state_ = State::IDLE;
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
@@ -188,12 +188,12 @@ void DallasSensor::loop() {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
LOG_ERROR("Unknown dallas sensor %s", Sensor(addr).id().c_str());
|
LOG_ERROR("Unknown sensor %s", Sensor(addr).id().c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sensorfails_++;
|
sensorfails_++;
|
||||||
LOG_ERROR("Invalid dallas sensor %s", Sensor(addr).id().c_str());
|
LOG_ERROR("Invalid sensor %s", Sensor(addr).id().c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!parasite_) {
|
if (!parasite_) {
|
||||||
@@ -211,7 +211,7 @@ void DallasSensor::loop() {
|
|||||||
scancnt_ = 0;
|
scancnt_ = 0;
|
||||||
} else if (scancnt_ == SCAN_START + 1) { // startup
|
} else if (scancnt_ == SCAN_START + 1) { // startup
|
||||||
firstscan_ = sensors_.size();
|
firstscan_ = sensors_.size();
|
||||||
// LOG_DEBUG("Adding %d dallas sensor(s) from first scan", firstscan_);
|
// LOG_DEBUG("Adding %d sensor(s) from first scan", firstscan_);
|
||||||
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
|
} else if ((scancnt_ <= 0) && (firstscan_ != sensors_.size())) { // check 2 times for no change of sensor #
|
||||||
scancnt_ = SCAN_START;
|
scancnt_ = SCAN_START;
|
||||||
sensors_.clear(); // restart scanning and clear to get correct numbering
|
sensors_.clear(); // restart scanning and clear to get correct numbering
|
||||||
@@ -223,7 +223,7 @@ void DallasSensor::loop() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DallasSensor::temperature_convert_complete() {
|
bool TemperatureSensor::temperature_convert_complete() {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (parasite_) {
|
if (parasite_) {
|
||||||
return true; // don't care, use the minimum time in loop
|
return true; // don't care, use the minimum time in loop
|
||||||
@@ -234,7 +234,7 @@ bool DallasSensor::temperature_convert_complete() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t DallasSensor::get_temperature_c(const uint8_t addr[]) {
|
int16_t TemperatureSensor::get_temperature_c(const uint8_t addr[]) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (!bus_.reset()) {
|
if (!bus_.reset()) {
|
||||||
LOG_ERROR("Bus reset failed before reading scratchpad from %s", Sensor(addr).id().c_str());
|
LOG_ERROR("Bus reset failed before reading scratchpad from %s", Sensor(addr).id().c_str());
|
||||||
@@ -297,8 +297,8 @@ int16_t DallasSensor::get_temperature_c(const uint8_t addr[]) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// update dallas information name and offset
|
// update temperature sensor information name and offset
|
||||||
bool DallasSensor::update(const std::string & id, const std::string & name, int16_t offset) {
|
bool TemperatureSensor::update(const std::string & id, const std::string & name, int16_t offset) {
|
||||||
// find the sensor
|
// find the sensor
|
||||||
for (auto & sensor : sensors_) {
|
for (auto & sensor : sensors_) {
|
||||||
if (sensor.id() == id) {
|
if (sensor.id() == id) {
|
||||||
@@ -346,7 +346,7 @@ bool DallasSensor::update(const std::string & id, const std::string & name, int1
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check to see if values have been updated
|
// check to see if values have been updated
|
||||||
bool DallasSensor::updated_values() {
|
bool TemperatureSensor::updated_values() {
|
||||||
if (changed_) {
|
if (changed_) {
|
||||||
changed_ = false;
|
changed_ = false;
|
||||||
return true;
|
return true;
|
||||||
@@ -355,13 +355,13 @@ bool DallasSensor::updated_values() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// list commands
|
// list commands
|
||||||
bool DallasSensor::command_commands(const char * value, const int8_t id, JsonObject & output) {
|
bool TemperatureSensor::command_commands(const char * value, const int8_t id, JsonObject & output) {
|
||||||
return Command::list(EMSdevice::DeviceType::DALLASSENSOR, output);
|
return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates JSON doc from values
|
// creates JSON doc from values
|
||||||
// returns false if there are no sensors
|
// returns false if there are no sensors
|
||||||
bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject & output) {
|
bool TemperatureSensor::command_info(const char * value, const int8_t id, JsonObject & output) {
|
||||||
if (sensors_.empty()) {
|
if (sensors_.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -387,7 +387,7 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
// called from emsesp.cpp, similar to the emsdevice->get_value_info
|
// called from emsesp.cpp, similar to the emsdevice->get_value_info
|
||||||
bool DallasSensor::get_value_info(JsonObject & output, const char * cmd, const int8_t id) {
|
bool TemperatureSensor::get_value_info(JsonObject & output, const char * cmd, const int8_t id) {
|
||||||
if (sensors_.empty()) {
|
if (sensors_.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -438,13 +438,13 @@ bool DallasSensor::get_value_info(JsonObject & output, const char * cmd, const i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// publish a single sensor to MQTT
|
// publish a single sensor to MQTT
|
||||||
void DallasSensor::publish_sensor(const Sensor & sensor) {
|
void TemperatureSensor::publish_sensor(const Sensor & sensor) {
|
||||||
if (Mqtt::enabled() && Mqtt::publish_single()) {
|
if (Mqtt::enabled() && Mqtt::publish_single()) {
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
snprintf(topic, sizeof(topic), "%s/%s", (F_(dallassensor)), sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s/%s", (F_(temperaturesensor)), sensor.name().c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(dallassensor)), "_data", sensor.name().c_str());
|
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(temperaturesensor)), "_data", sensor.name().c_str());
|
||||||
}
|
}
|
||||||
char payload[10];
|
char payload[10];
|
||||||
Mqtt::queue_publish(topic, Helpers::render_value(payload, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
Mqtt::queue_publish(topic, Helpers::render_value(payload, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
|
||||||
@@ -452,7 +452,7 @@ void DallasSensor::publish_sensor(const Sensor & sensor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send empty config topic to remove the entry from HA
|
// send empty config topic to remove the entry from HA
|
||||||
void DallasSensor::remove_ha_topic(const std::string & id) {
|
void TemperatureSensor::remove_ha_topic(const std::string & id) {
|
||||||
if (!Mqtt::ha_enabled()) {
|
if (!Mqtt::ha_enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -461,12 +461,12 @@ void DallasSensor::remove_ha_topic(const std::string & id) {
|
|||||||
std::string sensorid = id;
|
std::string sensorid = id;
|
||||||
std::replace(sensorid.begin(), sensorid.end(), '-', '_');
|
std::replace(sensorid.begin(), sensorid.end(), '-', '_');
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/dallassensor_%s/config", Mqtt::basename().c_str(), sensorid.c_str());
|
snprintf(topic, sizeof(topic), "sensor/%s/temperaturesensor_%s/config", Mqtt::basename().c_str(), sensorid.c_str());
|
||||||
Mqtt::queue_remove_topic(topic);
|
Mqtt::queue_remove_topic(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send all dallas sensor values as a JSON package to MQTT
|
// send all temperature sensor values as a JSON package to MQTT
|
||||||
void DallasSensor::publish_values(const bool force) {
|
void TemperatureSensor::publish_values(const bool force) {
|
||||||
if (!Mqtt::enabled()) {
|
if (!Mqtt::enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -499,7 +499,7 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the HA MQTT config
|
// create the HA MQTT config
|
||||||
// to e.g. homeassistant/sensor/ems-esp/dallassensor_28-233D-9497-0C03/config
|
// to e.g. homeassistant/sensor/ems-esp/temperaturesensor_28-233D-9497-0C03/config
|
||||||
if (Mqtt::ha_enabled()) {
|
if (Mqtt::ha_enabled()) {
|
||||||
if (!has_value && sensor.ha_registered) {
|
if (!has_value && sensor.ha_registered) {
|
||||||
remove_ha_topic(sensor.id());
|
remove_ha_topic(sensor.id());
|
||||||
@@ -511,7 +511,7 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
config["dev_cla"] = "temperature";
|
config["dev_cla"] = "temperature";
|
||||||
|
|
||||||
char stat_t[50];
|
char stat_t[50];
|
||||||
snprintf(stat_t, sizeof(stat_t), "%s/dallassensor_data", Mqtt::base().c_str()); // use base path
|
snprintf(stat_t, sizeof(stat_t), "%s/temperaturesensor_data", Mqtt::base().c_str()); // use base path
|
||||||
config["stat_t"] = stat_t;
|
config["stat_t"] = stat_t;
|
||||||
|
|
||||||
config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
||||||
@@ -529,9 +529,9 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
char uniq_s[70];
|
char uniq_s[70];
|
||||||
if (Mqtt::entity_format() == Mqtt::entitiyFormat::MULTI_SHORT) {
|
if (Mqtt::entity_format() == Mqtt::entitiyFormat::MULTI_SHORT) {
|
||||||
snprintf(uniq_s, sizeof(uniq_s), "%s_dallassensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
|
snprintf(uniq_s, sizeof(uniq_s), "%s_temperaturesensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(uniq_s, sizeof(uniq_s), "dallassensor_%s", sensor.id().c_str());
|
snprintf(uniq_s, sizeof(uniq_s), "temperaturesensor_%s", sensor.id().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
config["obj_id"] = uniq_s;
|
config["obj_id"] = uniq_s;
|
||||||
@@ -553,7 +553,7 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
std::string sensorid = sensor.id();
|
std::string sensorid = sensor.id();
|
||||||
std::replace(sensorid.begin(), sensorid.end(), '-', '_');
|
std::replace(sensorid.begin(), sensorid.end(), '-', '_');
|
||||||
|
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/dallassensor_%s/config", Mqtt::basename().c_str(), sensorid.c_str());
|
snprintf(topic, sizeof(topic), "sensor/%s/temperaturesensor_%s/config", Mqtt::basename().c_str(), sensorid.c_str());
|
||||||
|
|
||||||
Mqtt::queue_ha(topic, config.as<JsonObject>());
|
Mqtt::queue_ha(topic, config.as<JsonObject>());
|
||||||
|
|
||||||
@@ -562,12 +562,12 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Mqtt::queue_publish("dallassensor_data", doc.as<JsonObject>());
|
Mqtt::queue_publish("temperaturesensor_data", doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// skip crc from id
|
// skip crc from id
|
||||||
DallasSensor::Sensor::Sensor(const uint8_t addr[])
|
TemperatureSensor::Sensor::Sensor(const uint8_t addr[])
|
||||||
: internal_id_(((uint64_t)addr[0] << 48) | ((uint64_t)addr[1] << 40) | ((uint64_t)addr[2] << 32) | ((uint64_t)addr[3] << 24) | ((uint64_t)addr[4] << 16)
|
: internal_id_(((uint64_t)addr[0] << 48) | ((uint64_t)addr[1] << 40) | ((uint64_t)addr[2] << 32) | ((uint64_t)addr[3] << 24) | ((uint64_t)addr[4] << 16)
|
||||||
| ((uint64_t)addr[5] << 8) | ((uint64_t)addr[6])) {
|
| ((uint64_t)addr[5] << 8) | ((uint64_t)addr[6])) {
|
||||||
// create ID string
|
// create ID string
|
||||||
@@ -584,14 +584,14 @@ DallasSensor::Sensor::Sensor(const uint8_t addr[])
|
|||||||
offset_ = 0; // 0 degrees offset
|
offset_ = 0; // 0 degrees offset
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DallasSensor::get_id(const uint8_t addr[]) {
|
uint64_t TemperatureSensor::get_id(const uint8_t addr[]) {
|
||||||
return (((uint64_t)addr[0] << 48) | ((uint64_t)addr[1] << 40) | ((uint64_t)addr[2] << 32) | ((uint64_t)addr[3] << 24) | ((uint64_t)addr[4] << 16)
|
return (((uint64_t)addr[0] << 48) | ((uint64_t)addr[1] << 40) | ((uint64_t)addr[2] << 32) | ((uint64_t)addr[3] << 24) | ((uint64_t)addr[4] << 16)
|
||||||
| ((uint64_t)addr[5] << 8) | ((uint64_t)addr[6]));
|
| ((uint64_t)addr[5] << 8) | ((uint64_t)addr[6]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the name from the customization service
|
// find the name from the customization service
|
||||||
// if empty, return the ID as a string
|
// if empty, return the ID as a string
|
||||||
std::string DallasSensor::Sensor::name() const {
|
std::string TemperatureSensor::Sensor::name() const {
|
||||||
if (name_.empty()) {
|
if (name_.empty()) {
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
@@ -600,12 +600,12 @@ std::string DallasSensor::Sensor::name() const {
|
|||||||
|
|
||||||
// look up in customization service for a specific sensor
|
// look up in customization service for a specific sensor
|
||||||
// and set the name and offset from that entry if it exists
|
// and set the name and offset from that entry if it exists
|
||||||
bool DallasSensor::Sensor::apply_customization() {
|
bool TemperatureSensor::Sensor::apply_customization() {
|
||||||
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
EMSESP::webCustomizationService.read([&](WebCustomization & settings) {
|
||||||
auto sensors = settings.sensorCustomizations;
|
auto sensors = settings.sensorCustomizations;
|
||||||
if (!sensors.empty()) {
|
if (!sensors.empty()) {
|
||||||
for (const auto & sensor : sensors) {
|
for (const auto & sensor : sensors) {
|
||||||
LOG_DEBUG("Loading customization for dallas sensor %s", sensor.id.c_str());
|
LOG_DEBUG("Loading customization for temperature sensor %s", sensor.id.c_str());
|
||||||
if (id_ == sensor.id) {
|
if (id_ == sensor.id) {
|
||||||
set_name(sensor.name);
|
set_name(sensor.name);
|
||||||
set_offset(sensor.offset);
|
set_offset(sensor.offset);
|
||||||
@@ -621,8 +621,8 @@ bool DallasSensor::Sensor::apply_customization() {
|
|||||||
|
|
||||||
// hard coded tests
|
// hard coded tests
|
||||||
#if defined(EMSESP_TEST)
|
#if defined(EMSESP_TEST)
|
||||||
void DallasSensor::test() {
|
void TemperatureSensor::test() {
|
||||||
// add 2 dallas sensors
|
// add 2 temperature sensors
|
||||||
uint8_t addr[ADDR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
|
uint8_t addr[ADDR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||||
sensors_.emplace_back(addr);
|
sensors_.emplace_back(addr);
|
||||||
sensors_.back().temperature_c = 123;
|
sensors_.back().temperature_c = 123;
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
// code originally written by nomis - https://github.com/nomis
|
// code originally written by nomis - https://github.com/nomis
|
||||||
|
|
||||||
#ifndef EMSESP_DALLASSENSOR_H
|
#ifndef EMSESP_TEMPERATURESENSOR_H
|
||||||
#define EMSESP_DALLASSENSOR_H
|
#define EMSESP_TEMPERATURESENSOR_H
|
||||||
|
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
class DallasSensor {
|
class TemperatureSensor {
|
||||||
public:
|
public:
|
||||||
class Sensor {
|
class Sensor {
|
||||||
public:
|
public:
|
||||||
@@ -73,8 +73,8 @@ class DallasSensor {
|
|||||||
int16_t offset_;
|
int16_t offset_;
|
||||||
};
|
};
|
||||||
|
|
||||||
DallasSensor() = default;
|
TemperatureSensor() = default;
|
||||||
~DallasSensor() = default;
|
~TemperatureSensor() = default;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void loop();
|
void loop();
|
||||||
@@ -97,7 +97,7 @@ class DallasSensor {
|
|||||||
return sensorfails_;
|
return sensorfails_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dallas_enabled() {
|
bool sensor_enabled() {
|
||||||
return (dallas_gpio_ != 0);
|
return (dallas_gpio_ != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ class DallasSensor {
|
|||||||
static constexpr size_t SCRATCHPAD_CONFIG = 4;
|
static constexpr size_t SCRATCHPAD_CONFIG = 4;
|
||||||
static constexpr size_t SCRATCHPAD_CNT_REM = 6;
|
static constexpr size_t SCRATCHPAD_CNT_REM = 6;
|
||||||
|
|
||||||
// dallas chips
|
// dallas chip types
|
||||||
static constexpr uint8_t TYPE_DS18B20 = 0x28;
|
static constexpr uint8_t TYPE_DS18B20 = 0x28;
|
||||||
static constexpr uint8_t TYPE_DS18S20 = 0x10;
|
static constexpr uint8_t TYPE_DS18S20 = 0x10;
|
||||||
static constexpr uint8_t TYPE_DS1822 = 0x22;
|
static constexpr uint8_t TYPE_DS1822 = 0x22;
|
||||||
@@ -643,24 +643,24 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == "dallas") {
|
if (command == "temperature") {
|
||||||
shell.printfln("Testing adding Dallas sensor");
|
shell.printfln("Testing adding Temperature sensor");
|
||||||
emsesp::EMSESP::dallassensor_.test();
|
emsesp::EMSESP::temperaturesensor_.test();
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == "dallas_full") {
|
if (command == "temperature_full") {
|
||||||
shell.printfln("Testing adding and changing Dallas sensor");
|
shell.printfln("Testing adding and changing Temperature sensor");
|
||||||
Mqtt::ha_enabled(true);
|
Mqtt::ha_enabled(true);
|
||||||
Mqtt::nested_format(1);
|
Mqtt::nested_format(1);
|
||||||
// Mqtt::nested_format(0);
|
// Mqtt::nested_format(0);
|
||||||
|
|
||||||
emsesp::EMSESP::dallassensor_.test();
|
emsesp::EMSESP::temperaturesensor_.test();
|
||||||
shell.invoke_command("show");
|
shell.invoke_command("show");
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
|
|
||||||
// rename
|
// rename
|
||||||
EMSESP::dallassensor_.update("01-0203-0405-0607", "testdallas", 2);
|
EMSESP::temperaturesensor_.update("01-0203-0405-0607", "testtemperature", 2);
|
||||||
shell.invoke_command("show");
|
shell.invoke_command("show");
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
ok = true;
|
ok = true;
|
||||||
@@ -923,10 +923,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
requestX.url("/api/dallassensor/xxxx");
|
requestX.url("/api/temperaturesensor/xxxx");
|
||||||
EMSESP::webAPIService.webAPIService_get(&requestX);
|
EMSESP::webAPIService.webAPIService_get(&requestX);
|
||||||
emsesp::EMSESP::logger().notice("****");
|
emsesp::EMSESP::logger().notice("****");
|
||||||
requestX.url("/api/dallassensor/info");
|
requestX.url("/api/temperaturesensor/info");
|
||||||
EMSESP::webAPIService.webAPIService_get(&requestX);
|
EMSESP::webAPIService.webAPIService_get(&requestX);
|
||||||
return;
|
return;
|
||||||
*/
|
*/
|
||||||
@@ -1091,15 +1091,15 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
char data6[] = "{\"id\":2,\"devicevalue\":{\"v\":\"44\",\"u\":1,\"n\":\"hc2 selected room temperature\",\"c\":\"hc2/seltemp\"}";
|
char data6[] = "{\"id\":2,\"devicevalue\":{\"v\":\"44\",\"u\":1,\"n\":\"hc2 selected room temperature\",\"c\":\"hc2/seltemp\"}";
|
||||||
deserializeJson(doc, data6);
|
deserializeJson(doc, data6);
|
||||||
json = doc.as<JsonVariant>();
|
json = doc.as<JsonVariant>();
|
||||||
request.url("/rest/writeValue");
|
request.url("/rest/writeDeviceValue");
|
||||||
EMSESP::webDataService.write_value(&request, json);
|
EMSESP::webDataService.write_device_value(&request, json);
|
||||||
|
|
||||||
// write value from web - testing hc9/seltemp - should fail!
|
// write value from web - testing hc9/seltemp - should fail!
|
||||||
char data7[] = "{\"id\":2,\"devicevalue\":{\"v\":\"55\",\"u\":1,\"n\":\"hc2 selected room temperature\",\"c\":\"hc9/seltemp\"}";
|
char data7[] = "{\"id\":2,\"devicevalue\":{\"v\":\"55\",\"u\":1,\"n\":\"hc2 selected room temperature\",\"c\":\"hc9/seltemp\"}";
|
||||||
deserializeJson(doc, data7);
|
deserializeJson(doc, data7);
|
||||||
json = doc.as<JsonVariant>();
|
json = doc.as<JsonVariant>();
|
||||||
request.url("/rest/writeValue");
|
request.url("/rest/writeDeviceValue");
|
||||||
EMSESP::webDataService.write_value(&request, json);
|
EMSESP::webDataService.write_device_value(&request, json);
|
||||||
|
|
||||||
// emsesp::EMSESP::logger().notice("*");
|
// emsesp::EMSESP::logger().notice("*");
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace emsesp {
|
|||||||
// #define EMSESP_DEBUG_DEFAULT "dv"
|
// #define EMSESP_DEBUG_DEFAULT "dv"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "lastcode"
|
// #define EMSESP_DEBUG_DEFAULT "lastcode"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "2thermostats"
|
// #define EMSESP_DEBUG_DEFAULT "2thermostats"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "dallas"
|
// #define EMSESP_DEBUG_DEFAULT "temperature"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "analog"
|
// #define EMSESP_DEBUG_DEFAULT "analog"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "api_values"
|
// #define EMSESP_DEBUG_DEFAULT "api_values"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_post"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt_post"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.6.0-dev.10"
|
#define EMSESP_APP_VERSION "3.6.0-dev.11"
|
||||||
|
|||||||
@@ -57,17 +57,17 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
|
|
||||||
// this creates the customization file, saving it to the FS
|
// this creates the customization file, saving it to the FS
|
||||||
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
||||||
// Dallas Sensor customization
|
// Temperature Sensor customization
|
||||||
JsonArray sensorsJson = root.createNestedArray("sensors");
|
JsonArray sensorsJson = root.createNestedArray("ts");
|
||||||
for (const SensorCustomization & sensor : settings.sensorCustomizations) {
|
for (const SensorCustomization & sensor : settings.sensorCustomizations) {
|
||||||
JsonObject sensorJson = sensorsJson.createNestedObject();
|
JsonObject sensorJson = sensorsJson.createNestedObject();
|
||||||
sensorJson["id"] = sensor.id; // is
|
sensorJson["id"] = sensor.id; // ID of chip
|
||||||
sensorJson["name"] = sensor.name; // n
|
sensorJson["name"] = sensor.name; // n
|
||||||
sensorJson["offset"] = sensor.offset; // o
|
sensorJson["offset"] = sensor.offset; // o
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analog Sensor customization
|
// Analog Sensor customization
|
||||||
JsonArray analogJson = root.createNestedArray("analogs");
|
JsonArray analogJson = root.createNestedArray("as");
|
||||||
for (const AnalogCustomization & sensor : settings.analogCustomizations) {
|
for (const AnalogCustomization & sensor : settings.analogCustomizations) {
|
||||||
JsonObject sensorJson = analogJson.createNestedObject();
|
JsonObject sensorJson = analogJson.createNestedObject();
|
||||||
sensorJson["gpio"] = sensor.gpio; // g
|
sensorJson["gpio"] = sensor.gpio; // g
|
||||||
@@ -98,7 +98,7 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
|
|||||||
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
|
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
|
||||||
#ifdef EMSESP_STANDALONE
|
#ifdef EMSESP_STANDALONE
|
||||||
// invoke some fake data for testing
|
// invoke some fake data for testing
|
||||||
const char * json = "{\"sensors\":[],\"analogs\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
|
const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom "
|
||||||
"name for heating active\",\"08tapwateractive\"]}]}";
|
"name for heating active\",\"08tapwateractive\"]}]}";
|
||||||
|
|
||||||
StaticJsonDocument<500> doc;
|
StaticJsonDocument<500> doc;
|
||||||
@@ -111,10 +111,10 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
|||||||
Serial.println(COLOR_RESET);
|
Serial.println(COLOR_RESET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dallas Sensor customization
|
// Temperature Sensor customization
|
||||||
settings.sensorCustomizations.clear();
|
settings.sensorCustomizations.clear();
|
||||||
if (root["sensors"].is<JsonArray>()) {
|
if (root["ts"].is<JsonArray>()) {
|
||||||
for (const JsonObject sensorJson : root["sensors"].as<JsonArray>()) {
|
for (const JsonObject sensorJson : root["ts"].as<JsonArray>()) {
|
||||||
// create each of the sensor, overwriting any previous settings
|
// create each of the sensor, overwriting any previous settings
|
||||||
auto sensor = SensorCustomization();
|
auto sensor = SensorCustomization();
|
||||||
sensor.id = sensorJson["id"].as<std::string>();
|
sensor.id = sensorJson["id"].as<std::string>();
|
||||||
@@ -126,8 +126,8 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
|||||||
|
|
||||||
// Analog Sensor customization
|
// Analog Sensor customization
|
||||||
settings.analogCustomizations.clear();
|
settings.analogCustomizations.clear();
|
||||||
if (root["analogs"].is<JsonArray>()) {
|
if (root["as"].is<JsonArray>()) {
|
||||||
for (const JsonObject analogJson : root["analogs"].as<JsonArray>()) {
|
for (const JsonObject analogJson : root["as"].as<JsonArray>()) {
|
||||||
// create each of the sensor, overwriting any previous settings
|
// create each of the sensor, overwriting any previous settings
|
||||||
auto sensor = AnalogCustomization();
|
auto sensor = AnalogCustomization();
|
||||||
sensor.gpio = analogJson["gpio"];
|
sensor.gpio = analogJson["gpio"];
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// Customization for dallas sensor
|
// Customization for temperature sensor
|
||||||
class SensorCustomization {
|
class SensorCustomization {
|
||||||
public:
|
public:
|
||||||
std::string id;
|
std::string id;
|
||||||
|
|||||||
@@ -25,12 +25,13 @@ using namespace std::placeholders; // for `_1` etc
|
|||||||
WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager)
|
WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||||
: _device_data_handler(DEVICE_DATA_SERVICE_PATH,
|
: _device_data_handler(DEVICE_DATA_SERVICE_PATH,
|
||||||
securityManager->wrapCallback(std::bind(&WebDataService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
|
securityManager->wrapCallback(std::bind(&WebDataService::device_data, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED))
|
||||||
, _write_value_handler(WRITE_VALUE_SERVICE_PATH,
|
, _write_value_handler(WRITE_DEVICE_VALUE_SERVICE_PATH,
|
||||||
securityManager->wrapCallback(std::bind(&WebDataService::write_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
securityManager->wrapCallback(std::bind(&WebDataService::write_device_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
||||||
, _write_sensor_handler(WRITE_SENSOR_SERVICE_PATH,
|
, _write_temperature_handler(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH,
|
||||||
securityManager->wrapCallback(std::bind(&WebDataService::write_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2),
|
||||||
, _write_analog_handler(WRITE_ANALOG_SERVICE_PATH,
|
AuthenticationPredicates::IS_ADMIN))
|
||||||
securityManager->wrapCallback(std::bind(&WebDataService::write_analog, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
, _write_analog_handler(WRITE_ANALOG_SENSOR_SERVICE_PATH,
|
||||||
|
securityManager->wrapCallback(std::bind(&WebDataService::write_analog_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||||
server->on(CORE_DATA_SERVICE_PATH,
|
server->on(CORE_DATA_SERVICE_PATH,
|
||||||
HTTP_GET,
|
HTTP_GET,
|
||||||
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
@@ -51,9 +52,9 @@ WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securi
|
|||||||
_write_value_handler.setMaxContentLength(256);
|
_write_value_handler.setMaxContentLength(256);
|
||||||
server->addHandler(&_write_value_handler);
|
server->addHandler(&_write_value_handler);
|
||||||
|
|
||||||
_write_sensor_handler.setMethod(HTTP_POST);
|
_write_temperature_handler.setMethod(HTTP_POST);
|
||||||
_write_sensor_handler.setMaxContentLength(256);
|
_write_temperature_handler.setMaxContentLength(256);
|
||||||
server->addHandler(&_write_sensor_handler);
|
server->addHandler(&_write_temperature_handler);
|
||||||
|
|
||||||
_write_analog_handler.setMethod(HTTP_POST);
|
_write_analog_handler.setMethod(HTTP_POST);
|
||||||
_write_analog_handler.setMaxContentLength(256);
|
_write_analog_handler.setMaxContentLength(256);
|
||||||
@@ -103,11 +104,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
|||||||
obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values)
|
obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sensors stuff
|
root["connected"] = EMSESP::bus_status() != 2;
|
||||||
root["s_n"] = Helpers::translated_word(FL_(sensors_device));
|
|
||||||
root["active_sensors"] = EMSESP::dallassensor_.no_sensors() + (EMSESP::analogsensor_.analog_enabled() ? EMSESP::analogsensor_.no_sensors() : 0);
|
|
||||||
root["analog_enabled"] = EMSESP::analogsensor_.analog_enabled();
|
|
||||||
root["connected"] = EMSESP::bus_status() != 2;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@@ -115,15 +112,14 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
|||||||
|
|
||||||
// sensor data - sends back to web
|
// sensor data - sends back to web
|
||||||
// /sensorData endpoint
|
// /sensorData endpoint
|
||||||
// the "sensors" and "analogs" are arrays and must exist
|
|
||||||
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE);
|
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
// dallas sensors
|
// temperature sensors
|
||||||
JsonArray sensors = root.createNestedArray("sensors");
|
JsonArray sensors = root.createNestedArray("ts");
|
||||||
if (EMSESP::dallassensor_.have_sensors()) {
|
if (EMSESP::temperaturesensor_.have_sensors()) {
|
||||||
for (const auto & sensor : EMSESP::dallassensor_.sensors()) {
|
for (const auto & sensor : EMSESP::temperaturesensor_.sensors()) {
|
||||||
JsonObject obj = sensors.createNestedObject();
|
JsonObject obj = sensors.createNestedObject();
|
||||||
obj["id"] = sensor.id(); // id as string
|
obj["id"] = sensor.id(); // id as string
|
||||||
obj["n"] = sensor.name(); // name
|
obj["n"] = sensor.name(); // name
|
||||||
@@ -144,28 +140,23 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// analog sensors
|
// analog sensors
|
||||||
JsonArray analogs = root.createNestedArray("analogs");
|
JsonArray analogs = root.createNestedArray("as");
|
||||||
if (EMSESP::analog_enabled() && EMSESP::analogsensor_.have_sensors()) {
|
if (EMSESP::analog_enabled() && EMSESP::analogsensor_.have_sensors()) {
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
char buffer[3];
|
|
||||||
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
||||||
// don't send if it's marked for removal
|
JsonObject obj = analogs.createNestedObject();
|
||||||
if (sensor.type() != AnalogSensor::AnalogType::MARK_DELETED) {
|
obj["id"] = ++count; // needed for sorting table
|
||||||
count++;
|
obj["g"] = sensor.gpio();
|
||||||
JsonObject obj = analogs.createNestedObject();
|
obj["n"] = sensor.name();
|
||||||
obj["id"] = Helpers::smallitoa(buffer, count); // needed for sorting table
|
obj["u"] = sensor.uom();
|
||||||
obj["g"] = sensor.gpio();
|
obj["o"] = sensor.offset();
|
||||||
obj["n"] = sensor.name();
|
obj["f"] = sensor.factor();
|
||||||
obj["u"] = sensor.uom();
|
obj["t"] = sensor.type();
|
||||||
obj["o"] = sensor.offset();
|
|
||||||
obj["f"] = sensor.factor();
|
|
||||||
obj["t"] = sensor.type();
|
|
||||||
|
|
||||||
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) {
|
||||||
obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float
|
obj["v"] = Helpers::transformNumFloat(sensor.value(), 0); // is optional and is a float
|
||||||
} else {
|
} else {
|
||||||
obj["v"] = 0; // must have a value for web sorting to work
|
obj["v"] = 0; // must have a value for web sorting to work
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,7 +217,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
|
|||||||
|
|
||||||
// takes a command and its data value from a specific EMS Device, from the Web
|
// takes a command and its data value from a specific EMS Device, from the Web
|
||||||
// assumes the service has been checked for admin authentication
|
// assumes the service has been checked for admin authentication
|
||||||
void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
JsonObject dv = json["devicevalue"];
|
JsonObject dv = json["devicevalue"];
|
||||||
uint8_t unique_id = json["id"];
|
uint8_t unique_id = json["id"];
|
||||||
@@ -313,9 +304,9 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant &
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// takes a dallas sensor name and optional offset from the WebUI and update the customization settings
|
// takes a temperaturesensor name and optional offset from the WebUI and update the customization settings
|
||||||
// via the Dallas service
|
// via the temperaturesensor service
|
||||||
void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
JsonObject sensor = json;
|
JsonObject sensor = json;
|
||||||
@@ -329,7 +320,7 @@ void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant &
|
|||||||
if (EMSESP::system_.fahrenheit()) {
|
if (EMSESP::system_.fahrenheit()) {
|
||||||
offset10 = offset / 0.18;
|
offset10 = offset / 0.18;
|
||||||
}
|
}
|
||||||
ok = EMSESP::dallassensor_.update(id, name, offset10);
|
ok = EMSESP::temperaturesensor_.update(id, name, offset10);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||||
@@ -337,18 +328,19 @@ void WebDataService::write_sensor(AsyncWebServerRequest * request, JsonVariant &
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update the analog record, or create a new one
|
// update the analog record, or create a new one
|
||||||
void WebDataService::write_analog(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (json.is<JsonObject>()) {
|
if (json.is<JsonObject>()) {
|
||||||
JsonObject analog = json;
|
JsonObject analog = json;
|
||||||
|
|
||||||
uint8_t gpio = analog["gpio"]; // this is the unique key, the GPIO
|
uint8_t gpio = analog["gpio"];
|
||||||
std::string name = analog["name"];
|
std::string name = analog["name"];
|
||||||
double factor = analog["factor"];
|
double factor = analog["factor"];
|
||||||
double offset = analog["offset"];
|
double offset = analog["offset"];
|
||||||
uint8_t uom = analog["uom"];
|
uint8_t uom = analog["uom"];
|
||||||
int8_t type = analog["type"];
|
int8_t type = analog["type"];
|
||||||
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type);
|
bool deleted = analog["deleted"];
|
||||||
|
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type, deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||||
* Copyright 2020-2023 Paul Derbyshire
|
* Copyright 2020-2023 Paul Derbyshire
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
#define SENSOR_DATA_SERVICE_PATH "/rest/sensorData"
|
#define SENSOR_DATA_SERVICE_PATH "/rest/sensorData"
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
#define WRITE_VALUE_SERVICE_PATH "/rest/writeValue"
|
#define WRITE_DEVICE_VALUE_SERVICE_PATH "/rest/writeDeviceValue"
|
||||||
#define WRITE_SENSOR_SERVICE_PATH "/rest/writeSensor"
|
#define WRITE_TEMPERATURE_SENSOR_SERVICE_PATH "/rest/writeTemperatureSensor"
|
||||||
#define WRITE_ANALOG_SERVICE_PATH "/rest/writeAnalog"
|
#define WRITE_ANALOG_SENSOR_SERVICE_PATH "/rest/writeAnalogSensor"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ class WebDataService {
|
|||||||
|
|
||||||
// POST
|
// POST
|
||||||
void device_data(AsyncWebServerRequest * request, JsonVariant & json);
|
void device_data(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void write_value(AsyncWebServerRequest * request, JsonVariant & json);
|
void write_device_value(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void write_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
void write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void write_analog(AsyncWebServerRequest * request, JsonVariant & json);
|
void write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||||
void scan_devices(AsyncWebServerRequest * request);
|
void scan_devices(AsyncWebServerRequest * request);
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler _device_data_handler, _write_value_handler, _write_sensor_handler, _write_analog_handler;
|
AsyncCallbackJsonWebHandler _device_data_handler, _write_value_handler, _write_temperature_handler, _write_analog_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -176,13 +176,13 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
|||||||
settings.pbutton_gpio = root["pbutton_gpio"] | default_pbutton_gpio;
|
settings.pbutton_gpio = root["pbutton_gpio"] | default_pbutton_gpio;
|
||||||
check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON);
|
check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON);
|
||||||
|
|
||||||
// dallas
|
// temperaturesensor
|
||||||
prev = settings.dallas_gpio;
|
prev = settings.dallas_gpio;
|
||||||
settings.dallas_gpio = root["dallas_gpio"] | default_dallas_gpio;
|
settings.dallas_gpio = root["dallas_gpio"] | default_dallas_gpio;
|
||||||
check_flag(prev, settings.dallas_gpio, ChangeFlags::DALLAS);
|
check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR);
|
||||||
prev = settings.dallas_parasite;
|
prev = settings.dallas_parasite;
|
||||||
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
|
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
|
||||||
check_flag(prev, settings.dallas_parasite, ChangeFlags::DALLAS);
|
check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR);
|
||||||
|
|
||||||
// shower
|
// shower
|
||||||
prev = settings.shower_timer;
|
prev = settings.shower_timer;
|
||||||
@@ -301,8 +301,8 @@ void WebSettingsService::onUpdate() {
|
|||||||
EMSESP::shower_.start();
|
EMSESP::shower_.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::DALLAS)) {
|
if (WebSettings::has_flags(WebSettings::ChangeFlags::SENSOR)) {
|
||||||
EMSESP::dallassensor_.start();
|
EMSESP::temperaturesensor_.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::UART)) {
|
if (WebSettings::has_flags(WebSettings::ChangeFlags::UART)) {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class WebSettings {
|
|||||||
UART = (1 << 0), // 1
|
UART = (1 << 0), // 1
|
||||||
SYSLOG = (1 << 1), // 2
|
SYSLOG = (1 << 1), // 2
|
||||||
ADC = (1 << 2), // 4 - analog
|
ADC = (1 << 2), // 4 - analog
|
||||||
DALLAS = (1 << 3), // 8
|
SENSOR = (1 << 3), // 8
|
||||||
SHOWER = (1 << 4), // 16
|
SHOWER = (1 << 4), // 16
|
||||||
LED = (1 << 5), // 32
|
LED = (1 << 5), // 32
|
||||||
BUTTON = (1 << 6), // 64
|
BUTTON = (1 << 6), // 64
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
|||||||
root["tx_mode"] = EMSESP::txservice_.tx_mode();
|
root["tx_mode"] = EMSESP::txservice_.tx_mode();
|
||||||
root["uptime"] = EMSbus::bus_uptime();
|
root["uptime"] = EMSbus::bus_uptime();
|
||||||
root["num_devices"] = EMSESP::count_devices(); // excluding Controller
|
root["num_devices"] = EMSESP::count_devices(); // excluding Controller
|
||||||
root["num_sensors"] = EMSESP::dallassensor_.no_sensors();
|
root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors();
|
||||||
root["num_analogs"] = EMSESP::analogsensor_.no_sensors();
|
root["num_analogs"] = EMSESP::analogsensor_.no_sensors();
|
||||||
|
|
||||||
JsonArray statsJson = root.createNestedArray("stats");
|
JsonArray statsJson = root.createNestedArray("stats");
|
||||||
@@ -148,12 +148,13 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
|||||||
statJson["f"] = EMSESP::txservice_.telegram_write_fail_count();
|
statJson["f"] = EMSESP::txservice_.telegram_write_fail_count();
|
||||||
statJson["q"] = EMSESP::txservice_.write_quality();
|
statJson["q"] = EMSESP::txservice_.write_quality();
|
||||||
|
|
||||||
if (EMSESP::dallassensor_.dallas_enabled()) {
|
if (EMSESP::temperaturesensor_.sensor_enabled()) {
|
||||||
statJson = statsJson.createNestedObject();
|
statJson = statsJson.createNestedObject();
|
||||||
statJson["id"] = 3;
|
statJson["id"] = 3;
|
||||||
statJson["s"] = EMSESP::dallassensor_.reads();
|
statJson["s"] = EMSESP::temperaturesensor_.reads();
|
||||||
statJson["f"] = EMSESP::dallassensor_.fails();
|
statJson["f"] = EMSESP::temperaturesensor_.fails();
|
||||||
statJson["q"] = EMSESP::dallassensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::dallassensor_.fails()) / EMSESP::dallassensor_.reads());
|
statJson["q"] =
|
||||||
|
EMSESP::temperaturesensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::temperaturesensor_.fails()) / EMSESP::temperaturesensor_.reads());
|
||||||
}
|
}
|
||||||
if (EMSESP::analog_enabled()) {
|
if (EMSESP::analog_enabled()) {
|
||||||
statJson = statsJson.createNestedObject();
|
statJson = statsJson.createNestedObject();
|
||||||
|
|||||||
Reference in New Issue
Block a user