mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Merge remote-tracking branch 'origin/dev'
This commit is contained in:
75
CHANGELOG.md
75
CHANGELOG.md
@@ -5,19 +5,42 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
# Changelog
|
# [3.4.2]
|
||||||
|
|
||||||
## [3.4.1] May 29 2022
|
## Added
|
||||||
|
|
||||||
### Fixed
|
- RC310 additions [#520](https://github.com/emsesp/EMS-ESP32/pull/520)
|
||||||
|
- damping
|
||||||
|
- wwprio for RC310 heating circuits
|
||||||
|
- switchonoptimization for RC310 heating circuits
|
||||||
|
- enum_controlmode for RC310 (new enum list)
|
||||||
|
- nofrostmode, reducemode, reducetemp & noreducetemp for RC310
|
||||||
|
- emergencyops and emergencytemp, wwmaxtemp, wwflowtempoffset and wwcomfort1 for RC310
|
||||||
|
- HM200 hybrid module [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
|
||||||
|
- AM200 alternative heatsource module [#573](https://github.com/emsesp/EMS-ESP32/issues/573)
|
||||||
|
- EM10 error module as gateway [#575](https://github.com/emsesp/EMS-ESP32/issues/575)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519)
|
||||||
|
- allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570)
|
||||||
|
- losing entitiy wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Shorten "friendly names" in Home Assistant [#555](https://github.com/emsesp/EMS-ESP32/issues/555)
|
||||||
|
|
||||||
|
- platformio 2.3.0 (IDF 4, Arduino 2)
|
||||||
|
- remove master-thermostat, support multiple thermostats
|
||||||
|
- merge up- and download in webui [#577](https://github.com/emsesp/EMS-ESP32/issues/577)
|
||||||
|
|
||||||
|
# [3.4.1] May 29 2022
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
- Fix memory leak in api [#524](https://github.com/emsesp/EMS-ESP32/issues/524)
|
- Fix memory leak in api [#524](https://github.com/emsesp/EMS-ESP32/issues/524)
|
||||||
|
|
||||||
### Changed
|
## Changed
|
||||||
|
|
||||||
- Controller data in web-ui only for IVT [#522](https://github.com/emsesp/EMS-ESP32/issues/522)
|
|
||||||
- Rename hidden `climate` to a more explaining name [#523](https://github.com/emsesp/EMS-ESP32/issues/523)
|
|
||||||
- Minor changes to the Customizations web page [#527](https://github.com/emsesp/EMS-ESP32/pull/527)
|
|
||||||
|
|
||||||
# [3.4.0] May 23 2022
|
# [3.4.0] May 23 2022
|
||||||
|
|
||||||
@@ -284,51 +307,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- power settings, disabling BLE and turning off Wifi sleep
|
|
||||||
- Rx and Tx counts to Heartbeat MQTT payload
|
|
||||||
- ethernet support
|
|
||||||
- id to info command to show only a heatingcircuit
|
|
||||||
- add sending devices that are not listed to 0x07
|
|
||||||
- extra MQTT boolean option for "ON" and "OFF"
|
|
||||||
- support for chunked MQTT payloads to allow large data sets > 2kb
|
|
||||||
- external Button support (#708) for resetting to factory defaults and other actions
|
|
||||||
- new console set command in `system`, `set board_profile <profile>` for quickly enabling cabled ethernet connections without using the captive wifi portal
|
|
||||||
- added in MQTT nested mode, for thermostat and mixer, like we had back in v2
|
|
||||||
- cascade MC400 (product-id 210) (3.0.0b6), power values for heating sources (3.0.1b1)
|
|
||||||
- values for wwMaxPower, wwFlowtempOffset
|
|
||||||
- RC300 `thermostat temp -1` to clear temporary setpoint in auto mode
|
|
||||||
- syslog port selectable (#744)
|
|
||||||
- individual mqtt commands (#31)
|
- individual mqtt commands (#31)
|
||||||
- board Profiles (#11)
|
- board Profiles (#11)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- telegrams matched to masterthermostat 0x18
|
|
||||||
- multiple roomcontrollers
|
|
||||||
- readback after write with delay (give ems-devices time to set the value)
|
|
||||||
- thermostat ES72/RC20 device 66 to command-set RC20_2
|
|
||||||
- MQTT payloads not adding to queue when MQTT is re-connecting (fixes #369)
|
|
||||||
- fix for HA topics with invalid command formats (#728)
|
|
||||||
- wrong position of values #723, #732
|
|
||||||
- OTA Upload via Web on OSX
|
|
||||||
- Rx and Tx quality % would sometimes show > 100
|
- Rx and Tx quality % would sometimes show > 100
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- changed how telegram parameters are rendered for mqtt, console and web (#632)
|
|
||||||
- split `show values` in smaller packages (edited)
|
|
||||||
- extended length of IP/hostname from 32 to 48 chars (#676)
|
|
||||||
- check flowsensor for `tap_water_active`
|
|
||||||
- mqtt prefixed with `Base`
|
|
||||||
- count Dallas sensor fails
|
|
||||||
- switch from SPIFFS to LITTLEFS
|
|
||||||
- added ID to MQTT payloads which is the Device's product ID and used in HA to identify a unique HA device
|
|
||||||
- increased MQTT buffer and reduced wait time between publishes
|
|
||||||
- updated to the latest ArduinoJson library
|
|
||||||
- some names of mqtt-tags like in v2.2.1
|
|
||||||
- new ESP32 partition side to allow for smoother OTA and fallback
|
|
||||||
- network Gateway IP is optional (#682)emsesp/EMS-ESP
|
|
||||||
- moved to a new GitHub repo https://github.com/emsesp/EMS-ESP32
|
|
||||||
- invert LED changed to Hide LED. Default is off.
|
- invert LED changed to Hide LED. Default is off.
|
||||||
- renamed Scan Network to Scan WiFi Network
|
- renamed Scan Network to Scan WiFi Network
|
||||||
- added version to cmd=settings
|
- added version to cmd=settings
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -141,7 +141,7 @@ run: $(OUTPUT)
|
|||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(RM) -r $(BUILD) $(OUTPUT)
|
@$(RM) -rf $(BUILD) $(OUTPUT)
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo available targets: all run clean
|
@echo available targets: all run clean
|
||||||
|
|||||||
@@ -3,4 +3,3 @@
|
|||||||
# Firmware Installation
|
# Firmware Installation
|
||||||
|
|
||||||
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.
|
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,3 @@ This is a snapshot of the current "beta" development code and firmware binaries
|
|||||||
# Firmware Installation
|
# Firmware Installation
|
||||||
|
|
||||||
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.
|
Follow the instructions in the [documentation](https://emsesp.github.io/docs) on how to install the firmware binaries in the Assets below.
|
||||||
|
|
||||||
|
|||||||
8887
interface/package-lock.json
generated
8887
interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,33 +4,33 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:3080",
|
"proxy": "http://localhost:3080",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.9.0",
|
"@emotion/react": "^11.10.4",
|
||||||
"@emotion/styled": "^11.8.1",
|
"@emotion/styled": "^11.10.4",
|
||||||
"@msgpack/msgpack": "^2.7.2",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"@mui/icons-material": "^5.8.0",
|
"@mui/icons-material": "^5.10.3",
|
||||||
"@mui/material": "^5.8.1",
|
"@mui/material": "^5.10.5",
|
||||||
"@table-library/react-table-library": "^3.1.4",
|
"@table-library/react-table-library": "4.0.18",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.185",
|
||||||
"@types/node": "^17.0.36",
|
"@types/node": "^18.7.18",
|
||||||
"@types/react": "^18.0.9",
|
"@types/react": "^18.0.20",
|
||||||
"@types/react-dom": "^18.0.5",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.1.1",
|
"async-validator": "^4.2.5",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"notistack": "^2.0.5",
|
"notistack": "^2.0.5",
|
||||||
"parse-ms": "^3.0.0",
|
"parse-ms": "^3.0.0",
|
||||||
"react": "^18.1.0",
|
"react": "^18.2.0",
|
||||||
"react-app-rewired": "^2.2.1",
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-dom": "^18.1.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.1",
|
"react-dropzone": "^14.2.2",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.4.0",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.4.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typescript": "^4.7.2"
|
"typescript": "^4.8.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-app-rewired start",
|
"start": "react-app-rewired start",
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^2.0.16",
|
"nodemon": "^2.0.20",
|
||||||
"npm-run-all": "^4.1.5"
|
"npm-run-all": "^4.1.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const MqttSettingsForm: FC = () => {
|
|||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors}
|
fieldErrors={fieldErrors}
|
||||||
name="base"
|
name="base"
|
||||||
label="Bsse"
|
label="Base"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={data.base}
|
value={data.base}
|
||||||
|
|||||||
@@ -35,43 +35,44 @@ const ManageUsersForm: FC = () => {
|
|||||||
const authenticatedContext = useContext(AuthenticatedContext);
|
const authenticatedContext = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
const table_theme = useTheme({
|
const table_theme = useTheme({
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 90px 120px;
|
||||||
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
|
||||||
padding-left: 8px;
|
|
||||||
`,
|
`,
|
||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
font-weight: 500;
|
.th {
|
||||||
border-bottom: 1px solid #e0e0e0;
|
padding: 8px;
|
||||||
|
height: 42px;
|
||||||
|
font-weight: 500;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
Row: `
|
Row: `
|
||||||
&:nth-of-type(odd) {
|
.td {
|
||||||
|
padding: 8px;
|
||||||
|
border-top: 1px solid #565656;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(odd) .td {
|
||||||
background-color: #303030;
|
background-color: #303030;
|
||||||
}
|
}
|
||||||
&:nth-of-type(even) {
|
&:nth-of-type(even) .td {
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
}
|
}
|
||||||
border-top: 1px solid #565656;
|
|
||||||
border-bottom: 1px solid #565656;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
margin-bottom: -1px;
|
|
||||||
}
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: -1px;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
BaseCell: `
|
BaseCell: `
|
||||||
border-top: 1px solid transparent;
|
&:nth-of-type(2) {
|
||||||
border-right: 1px solid transparent;
|
text-align: center;
|
||||||
border-bottom: 1px solid transparent;
|
}
|
||||||
|
&:last-of-type {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,22 +131,22 @@ const ManageUsersForm: FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Table data={{ nodes: user_table }} theme={table_theme}>
|
<Table data={{ nodes: user_table }} theme={table_theme} layout={{ custom: true }}>
|
||||||
{(tableList: any) => (
|
{(tableList: any) => (
|
||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell>USERNAME</HeaderCell>
|
<HeaderCell resize>USERNAME</HeaderCell>
|
||||||
<HeaderCell>IS ADMIN</HeaderCell>
|
<HeaderCell stiff>IS ADMIN</HeaderCell>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((u: any) => (
|
{tableList.map((u: any) => (
|
||||||
<Row key={u.id} item={u}>
|
<Row key={u.id} item={u}>
|
||||||
<Cell>{u.username}</Cell>
|
<Cell>{u.username}</Cell>
|
||||||
<Cell>{u.admin ? <CheckIcon /> : <CloseIcon />}</Cell>
|
<Cell stiff>{u.admin ? <CheckIcon /> : <CloseIcon />}</Cell>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
<IconButton
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
disabled={!authenticatedContext.me.admin}
|
disabled={!authenticatedContext.me.admin}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
import { AxiosPromise } from 'axios';
|
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { AxiosPromise } from 'axios';
|
||||||
|
|
||||||
|
import { Typography, Button, Box } from '@mui/material';
|
||||||
|
|
||||||
import { FileUploadConfig } from '../../api/endpoints';
|
import { FileUploadConfig } from '../../api/endpoints';
|
||||||
import { MessageBox, SingleUpload, useFileUpload } from '../../components';
|
import { SingleUpload, useFileUpload } from '../../components';
|
||||||
|
|
||||||
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
|
|
||||||
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
|
import { extractErrorMessage } from '../../utils';
|
||||||
|
|
||||||
|
import * as EMSESP from '../../project/api';
|
||||||
|
|
||||||
interface UploadFileProps {
|
interface UploadFileProps {
|
||||||
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||||
@@ -11,16 +21,93 @@ interface UploadFileProps {
|
|||||||
const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||||
const [uploadFile, cancelUpload, uploading, uploadProgress] = useFileUpload({ upload: uploadGeneralFile });
|
const [uploadFile, cancelUpload, uploading, uploadProgress] = useFileUpload({ upload: uploadGeneralFile });
|
||||||
|
|
||||||
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
|
const saveFile = (json: any, endpoint: string) => {
|
||||||
|
const a = document.createElement('a');
|
||||||
|
const filename = 'emsesp_' + endpoint + '.json';
|
||||||
|
a.href = URL.createObjectURL(
|
||||||
|
new Blob([JSON.stringify(json, null, 2)], {
|
||||||
|
type: 'text/plain'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
a.setAttribute('download', filename);
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
enqueueSnackbar('File downloaded', { variant: 'info' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadSettings = async () => {
|
||||||
|
try {
|
||||||
|
const response = await EMSESP.getSettings();
|
||||||
|
if (response.status !== 200) {
|
||||||
|
enqueueSnackbar('Unable to get settings', { variant: 'error' });
|
||||||
|
} else {
|
||||||
|
saveFile(response.data, 'settings');
|
||||||
|
}
|
||||||
|
} catch (error: unknown) {
|
||||||
|
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadCustomizations = async () => {
|
||||||
|
try {
|
||||||
|
const response = await EMSESP.getCustomizations();
|
||||||
|
if (response.status !== 200) {
|
||||||
|
enqueueSnackbar('Unable to get customizations', { variant: 'error' });
|
||||||
|
} else {
|
||||||
|
saveFile(response.data, 'customizations');
|
||||||
|
}
|
||||||
|
} catch (error: unknown) {
|
||||||
|
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||||
|
Upload
|
||||||
|
</Typography>
|
||||||
{!uploading && (
|
{!uploading && (
|
||||||
<MessageBox
|
<Box mb={2} color="warning.main">
|
||||||
message="Upload a new firmware (.bin) file or an exported settings or customizations (.json) file below. EMS-ESP will restart afterwards to apply the new changes."
|
<Typography variant="body2">
|
||||||
level="warning"
|
Upload a new firmware (.bin) file, settings or customizations (.json) file below.
|
||||||
my={2}
|
</Typography>
|
||||||
/>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<SingleUpload onDrop={uploadFile} onCancel={cancelUpload} uploading={uploading} progress={uploadProgress} />
|
<SingleUpload onDrop={uploadFile} onCancel={cancelUpload} uploading={uploading} progress={uploadProgress} />
|
||||||
|
|
||||||
|
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||||
|
Download
|
||||||
|
</Typography>
|
||||||
|
{!uploading && (
|
||||||
|
<>
|
||||||
|
<Box color="warning.main">
|
||||||
|
<Typography mb={1} variant="body2">
|
||||||
|
Download the application settings. Be careful when sharing your settings as this file contains passwords
|
||||||
|
and other sensitive system information.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => downloadSettings()}>
|
||||||
|
settings
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Box color="warning.main">
|
||||||
|
<Typography mt={2} mb={1} variant="body2">
|
||||||
|
Download the entity customizations.
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
startIcon={<DownloadIcon />}
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={() => downloadCustomizations()}
|
||||||
|
>
|
||||||
|
customizations
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const System: FC = () => {
|
|||||||
<Tab value="log" label="System Log" />
|
<Tab value="log" label="System Log" />
|
||||||
|
|
||||||
{features.ota && <Tab value="ota" label="OTA Settings" disabled={!me.admin} />}
|
{features.ota && <Tab value="ota" label="OTA Settings" disabled={!me.admin} />}
|
||||||
{features.upload_firmware && <Tab value="upload" label="Upload" disabled={!me.admin} />}
|
{features.upload_firmware && <Tab value="upload" label="Upload/Download" disabled={!me.admin} />}
|
||||||
</RouterTabs>
|
</RouterTabs>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="status" element={<SystemStatusForm />} />
|
<Route path="status" element={<SystemStatusForm />} />
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const UploadFileForm: FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Upload File" titleGutter>
|
<SectionContent title="Upload/Download" titleGutter>
|
||||||
{restarting ? <RestartMonitor /> : <GeneralFileUpload uploadGeneralFile={uploadFile.current} />}
|
{restarting ? <RestartMonitor /> : <GeneralFileUpload uploadGeneralFile={uploadFile.current} />}
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const [coreData, setCoreData] = useState<CoreData>({ devices: [], active_sensors: 0, analog_enabled: false });
|
const [coreData, setCoreData] = useState<CoreData>({ connected: true, devices: [], 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 [sensorData, setSensorData] = useState<SensorData>({ sensors: [], analogs: [] });
|
||||||
const [deviceValue, setDeviceValue] = useState<DeviceValue>();
|
const [deviceValue, setDeviceValue] = useState<DeviceValue>();
|
||||||
@@ -88,185 +88,121 @@ const DashboardData: FC = () => {
|
|||||||
const [deviceDialog, setDeviceDialog] = useState<number>(-1);
|
const [deviceDialog, setDeviceDialog] = useState<number>(-1);
|
||||||
const [onlyFav, setOnlyFav] = useState(false);
|
const [onlyFav, setOnlyFav] = useState(false);
|
||||||
|
|
||||||
const device_theme = useTheme({
|
const common_theme = useTheme({
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
|
||||||
height: 46px;
|
|
||||||
&:focus {
|
|
||||||
z-index: 2;
|
|
||||||
border-top: 1px solid #177ac9;
|
|
||||||
border-bottom: 1px solid #177ac9;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
|
||||||
font-weight: 500;
|
.th {
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
Row: `
|
Row: `
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
border-top: 1px solid #565656;
|
|
||||||
border-bottom: 1px solid #565656;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
cursor: pointer;
|
||||||
&:not(:last-of-type) {
|
|
||||||
margin-bottom: -1px;
|
.td {
|
||||||
|
padding: 8px;
|
||||||
|
border-top: 1px solid #565656;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
}
|
}
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: -1px;
|
&.tr.tr-body.row-select.row-select-single-selected {
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
z-index: 2;
|
|
||||||
color: white;
|
|
||||||
border-top: 1px solid #177ac9;
|
|
||||||
border-bottom: 1px solid #177ac9;
|
|
||||||
},
|
|
||||||
&.tr.tr-body.row-select.row-select-single-selected, &.tr.tr-body.row-select.row-select-selected {
|
|
||||||
background-color: #3d4752;
|
background-color: #3d4752;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
z-index: 2;
|
}
|
||||||
|
|
||||||
|
&:hover .td {
|
||||||
border-top: 1px solid #177ac9;
|
border-top: 1px solid #177ac9;
|
||||||
border-bottom: 1px solid #177ac9;
|
border-bottom: 1px solid #177ac9;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
BaseCell: `
|
Cell: `
|
||||||
border-top: 1px solid transparent;
|
|
||||||
border-right: 1px solid transparent;
|
|
||||||
border-bottom: 1px solid transparent;
|
|
||||||
&:not(.stiff) > div {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
padding-left: 8px;
|
|
||||||
min-width: 42px;
|
|
||||||
width: 42px;
|
|
||||||
div {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
min-width: 100px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
&:nth-of-type(3) {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(4) {
|
|
||||||
text-align: center;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
&:last-of-type {
|
&:last-of-type {
|
||||||
padding-left: 0px;
|
text-align: right;
|
||||||
text-align: center;
|
},
|
||||||
width: 32px;
|
|
||||||
min-width: 32px;
|
|
||||||
max-width: 32px;
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
|
|
||||||
const data_theme = useTheme({
|
const device_theme = useTheme([
|
||||||
BaseRow: `
|
common_theme,
|
||||||
font-size: 14px;
|
{
|
||||||
color: white;
|
Table: `
|
||||||
height: 32px;
|
--data-table-library_grid-template-columns: 40px 100px repeat(1, minmax(0, 1fr)) 80px 40px;
|
||||||
`,
|
`,
|
||||||
HeaderRow: `
|
BaseRow: `
|
||||||
text-transform: uppercase;
|
.td {
|
||||||
background-color: black;
|
height: 42px;
|
||||||
color: #90CAF9;
|
}
|
||||||
border-bottom: 1px solid #e0e0e0;
|
`,
|
||||||
font-weight: 500;
|
BaseCell: `
|
||||||
`,
|
&:nth-of-type(2) {
|
||||||
Row: `
|
text-align: left;
|
||||||
&:nth-of-type(odd) {
|
},
|
||||||
background-color: #303030;
|
&:nth-of-type(4) {
|
||||||
}
|
text-align: center;
|
||||||
&:nth-of-type(even) {
|
}
|
||||||
background-color: #1e1e1e;
|
`,
|
||||||
}
|
HeaderRow: `
|
||||||
border-top: 1px solid #565656;
|
.th {
|
||||||
border-bottom: 1px solid #565656;
|
padding: 8px;
|
||||||
position: relative;
|
height: 42px;
|
||||||
z-index: 1;
|
font-weight: 500;
|
||||||
&:not(:last-of-type) {
|
`
|
||||||
margin-bottom: -1px;
|
}
|
||||||
}
|
]);
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: -1px;
|
const data_theme = useTheme([
|
||||||
}
|
common_theme,
|
||||||
&:hover {
|
{
|
||||||
z-index: 2;
|
Table: `
|
||||||
border-top: 1px solid #177ac9;
|
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 140px 40px;
|
||||||
border-bottom: 1px solid #177ac9;
|
`,
|
||||||
color: white;
|
BaseRow: `
|
||||||
}
|
.td {
|
||||||
`,
|
height: 32px;
|
||||||
BaseCell: `
|
}
|
||||||
padding-left: 16px;
|
`,
|
||||||
cursor: pointer;
|
BaseCell: `
|
||||||
border-top: 1px solid transparent;
|
&:nth-of-type(2) {
|
||||||
border-right: 1px solid transparent;
|
text-align: right;
|
||||||
border-bottom: 1px solid transparent;
|
},
|
||||||
&:not(.stiff) > div {
|
`,
|
||||||
white-space: nowrap;
|
HeaderRow: `
|
||||||
overflow: hidden;
|
.th {
|
||||||
text-overflow: ellipsis;
|
height: 32px;
|
||||||
}
|
}
|
||||||
&:nth-of-type(1) {
|
`,
|
||||||
width: 260px;
|
Row: `
|
||||||
}
|
&:nth-of-type(odd) .td {
|
||||||
&:nth-of-type(2) {
|
background-color: #303030;
|
||||||
flex: 1;
|
}
|
||||||
text-align: right;
|
`
|
||||||
}
|
}
|
||||||
&:last-of-type {
|
]);
|
||||||
padding-left: 0px;
|
|
||||||
text-align: center;
|
|
||||||
width: 32px;
|
|
||||||
min-width: 32px;
|
|
||||||
max-width: 32px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
HeaderCell: `
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
padding-left: 8px;
|
|
||||||
border-left: 1px solid #565656;
|
|
||||||
}
|
|
||||||
&:first-of-type {
|
|
||||||
border-left: 0px;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
});
|
|
||||||
|
|
||||||
const temperature_theme = useTheme([data_theme]);
|
const temperature_theme = useTheme([data_theme]);
|
||||||
|
|
||||||
const analog_theme = useTheme([
|
const analog_theme = useTheme([
|
||||||
data_theme,
|
data_theme,
|
||||||
{
|
{
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: 80px repeat(1, minmax(0, 1fr)) 120px 100px 40px;
|
||||||
|
`,
|
||||||
BaseCell: `
|
BaseCell: `
|
||||||
&:nth-of-type(1) {
|
|
||||||
width: 100px;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
&:nth-of-type(2) {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
},
|
||||||
&:nth-of-type(3) {
|
|
||||||
width: 100px;
|
|
||||||
min-width: 100px;
|
|
||||||
}
|
|
||||||
&:nth-of-type(4) {
|
&:nth-of-type(4) {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -536,6 +472,7 @@ const DashboardData: FC = () => {
|
|||||||
label={deviceValue.id.slice(2)}
|
label={deviceValue.id.slice(2)}
|
||||||
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
multiline={deviceValue.u ? false : true}
|
||||||
sx={{ width: '30ch' }}
|
sx={{ width: '30ch' }}
|
||||||
type={deviceValue.u ? 'number' : 'text'}
|
type={deviceValue.u ? 'number' : 'text'}
|
||||||
onChange={updateValue(setDeviceValue)}
|
onChange={updateValue(setDeviceValue)}
|
||||||
@@ -703,29 +640,30 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
const renderCoreData = () => (
|
const renderCoreData = () => (
|
||||||
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
|
<IconContext.Provider value={{ color: 'lightblue', size: '24', style: { verticalAlign: 'middle' } }}>
|
||||||
{coreData.devices.length === 0 && <MessageBox my={2} level="warning" message="Scanning for EMS devices..." />}
|
{!coreData.connected && <MessageBox my={2} level="error" message="EMSbus disconnected, check settings and board profile" />}
|
||||||
|
{coreData.connected && coreData.devices.length === 0 && <MessageBox my={2} level="warning" message="Scanning for EMS devices..." />}
|
||||||
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
|
<Table data={{ nodes: coreData.devices }} select={device_select} theme={device_theme} layout={{ custom: true }}>
|
||||||
{(tableList: any) => (
|
{(tableList: any) => (
|
||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
<HeaderCell>TYPE</HeaderCell>
|
<HeaderCell stiff>TYPE</HeaderCell>
|
||||||
<HeaderCell>DESCRIPTION</HeaderCell>
|
<HeaderCell resize>DESCRIPTION</HeaderCell>
|
||||||
<HeaderCell>ENTITIES</HeaderCell>
|
<HeaderCell stiff>ENTITIES</HeaderCell>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((device: Device, index: number) => (
|
{tableList.map((device: Device, index: number) => (
|
||||||
<Row key={device.id} item={device}>
|
<Row key={device.id} item={device}>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
<DeviceIcon type={device.t} />
|
<DeviceIcon type={device.t} />
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell>{device.t}</Cell>
|
<Cell stiff>{device.t}</Cell>
|
||||||
<Cell>{device.n}</Cell>
|
<Cell>{device.n}</Cell>
|
||||||
<Cell>{device.e}</Cell>
|
<Cell stiff>{device.e}</Cell>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
<IconButton size="small" onClick={() => setDeviceDialog(index)}>
|
<IconButton size="small" onClick={() => setDeviceDialog(index)}>
|
||||||
<InfoOutlinedIcon color="info" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
|
<InfoOutlinedIcon color="info" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -778,7 +716,7 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
||||||
{deviceData.label}
|
{deviceData.label}
|
||||||
</Typography>
|
</Typography>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
@@ -814,7 +752,7 @@ const DashboardData: FC = () => {
|
|||||||
ENTITY NAME
|
ENTITY NAME
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell>
|
<HeaderCell resize>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
||||||
@@ -824,7 +762,7 @@ const DashboardData: FC = () => {
|
|||||||
VALUE
|
VALUE
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
@@ -832,7 +770,7 @@ const DashboardData: FC = () => {
|
|||||||
<Row key={dv.id} item={dv} onClick={() => sendCommand(dv)}>
|
<Row key={dv.id} item={dv} onClick={() => sendCommand(dv)}>
|
||||||
<Cell>{renderNameCell(dv)}</Cell>
|
<Cell>{renderNameCell(dv)}</Cell>
|
||||||
<Cell>{formatValue(dv.v, dv.u)}</Cell>
|
<Cell>{formatValue(dv.v, dv.u)}</Cell>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
{dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
|
{dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
|
||||||
<IconButton size="small" onClick={() => sendCommand(dv)}>
|
<IconButton size="small" onClick={() => sendCommand(dv)}>
|
||||||
{isCmdOnly(dv) ? (
|
{isCmdOnly(dv) ? (
|
||||||
@@ -867,7 +805,7 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
const renderDallasData = () => (
|
const renderDallasData = () => (
|
||||||
<>
|
<>
|
||||||
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
||||||
Temperature Sensors
|
Temperature Sensors
|
||||||
</Typography>
|
</Typography>
|
||||||
<Table
|
<Table
|
||||||
@@ -890,7 +828,7 @@ const DashboardData: FC = () => {
|
|||||||
NAME
|
NAME
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell>
|
<HeaderCell stiff>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
style={{ fontSize: '14px', justifyContent: 'flex-end' }}
|
||||||
@@ -900,7 +838,7 @@ const DashboardData: FC = () => {
|
|||||||
TEMPERATURE
|
TEMPERATURE
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
@@ -926,7 +864,7 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
const renderAnalogData = () => (
|
const renderAnalogData = () => (
|
||||||
<>
|
<>
|
||||||
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="primary">
|
<Typography sx={{ pt: 2, pb: 1 }} variant="h6" color="secondary">
|
||||||
Analog Sensors
|
Analog Sensors
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@@ -935,7 +873,7 @@ const DashboardData: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell resize>
|
<HeaderCell stiff>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
@@ -955,7 +893,7 @@ const DashboardData: FC = () => {
|
|||||||
NAME
|
NAME
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell resize>
|
<HeaderCell stiff>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
style={{ fontSize: '14px', justifyContent: 'flex-start' }}
|
||||||
@@ -965,18 +903,18 @@ const DashboardData: FC = () => {
|
|||||||
TYPE
|
TYPE
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell>VALUE</HeaderCell>
|
<HeaderCell stiff>VALUE</HeaderCell>
|
||||||
<HeaderCell />
|
<HeaderCell stiff />
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((a: Analog) => (
|
{tableList.map((a: Analog) => (
|
||||||
<Row key={a.id} item={a} onClick={() => updateAnalog(a)}>
|
<Row key={a.id} item={a} onClick={() => updateAnalog(a)}>
|
||||||
<Cell>{a.g}</Cell>
|
<Cell stiff>{a.g}</Cell>
|
||||||
<Cell>{a.n}</Cell>
|
<Cell>{a.n}</Cell>
|
||||||
<Cell>{AnalogTypeNames[a.t]} </Cell>
|
<Cell stiff>{AnalogTypeNames[a.t]} </Cell>
|
||||||
<Cell>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
<Cell stiff>{a.t ? formatValue(a.v, a.u) : ''}</Cell>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
{me.admin && (
|
{me.admin && (
|
||||||
<IconButton onClick={() => updateAnalog(a)}>
|
<IconButton onClick={() => updateAnalog(a)}>
|
||||||
<EditIcon color="primary" sx={{ fontSize: 16 }} />
|
<EditIcon color="primary" sx={{ fontSize: 16 }} />
|
||||||
|
|||||||
@@ -88,65 +88,40 @@ const DashboardStatus: FC = () => {
|
|||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
const stats_theme = tableTheme({
|
const stats_theme = tableTheme({
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 90px 90px 80px;
|
||||||
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
|
||||||
height: 32px;
|
|
||||||
`,
|
`,
|
||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
font-weight: 500;
|
|
||||||
border-bottom: 1px solid #e0e0e0;
|
.th {
|
||||||
padding-left: 8px;
|
height: 42px;
|
||||||
|
font-weight: 500;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
Row: `
|
Row: `
|
||||||
&:nth-of-type(odd) {
|
.td {
|
||||||
|
padding: 8px;
|
||||||
|
border-top: 1px solid #565656;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(odd) .td {
|
||||||
background-color: #303030;
|
background-color: #303030;
|
||||||
}
|
}
|
||||||
&:nth-of-type(even) {
|
&:nth-of-type(even) .td {
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
}
|
}
|
||||||
border-top: 1px solid #565656;
|
|
||||||
border-bottom: 1px solid #565656;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
margin-bottom: -1px;
|
|
||||||
}
|
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: -1px;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
BaseCell: `
|
BaseCell: `
|
||||||
border-top: 1px solid transparent;
|
&:not(:first-of-type) {
|
||||||
border-right: 1px solid transparent;
|
text-align: center;
|
||||||
border-bottom: 1px solid transparent;
|
|
||||||
&:not(.stiff) > div {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
padding-left: 8px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
width: 70px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
&:nth-of-type(3) {
|
|
||||||
width: 40px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
&:last-of-type {
|
|
||||||
width: 75px;
|
|
||||||
text-align: right;
|
|
||||||
padding-right: 8px;
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
@@ -224,19 +199,19 @@ const DashboardStatus: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell></HeaderCell>
|
<HeaderCell resize></HeaderCell>
|
||||||
<HeaderCell>SUCCESS</HeaderCell>
|
<HeaderCell stiff>SUCCESS</HeaderCell>
|
||||||
<HeaderCell>FAIL</HeaderCell>
|
<HeaderCell stiff>FAIL</HeaderCell>
|
||||||
<HeaderCell>QUALITY</HeaderCell>
|
<HeaderCell stiff>QUALITY</HeaderCell>
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((stat: Stat) => (
|
{tableList.map((stat: Stat) => (
|
||||||
<Row key={stat.id} item={stat}>
|
<Row key={stat.id} item={stat}>
|
||||||
<Cell>{stat.id}</Cell>
|
<Cell>{stat.id}</Cell>
|
||||||
<Cell>{Intl.NumberFormat().format(stat.s)}</Cell>
|
<Cell stiff>{Intl.NumberFormat().format(stat.s)}</Cell>
|
||||||
<Cell>{Intl.NumberFormat().format(stat.f)}</Cell>
|
<Cell stiff>{Intl.NumberFormat().format(stat.f)}</Cell>
|
||||||
<Cell>{showQuality(stat)}</Cell>
|
<Cell stiff>{showQuality(stat)}</Cell>
|
||||||
</Row>
|
</Row>
|
||||||
))}
|
))}
|
||||||
</Body>
|
</Body>
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { FC, useContext } from 'react';
|
import { FC } from 'react';
|
||||||
|
|
||||||
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
|
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
|
||||||
|
|
||||||
import { SectionContent, ButtonRow, MessageBox } from '../components';
|
import { SectionContent } from '../components';
|
||||||
|
|
||||||
import { AuthenticatedContext } from '../contexts/authentication';
|
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { useSnackbar } from 'notistack';
|
||||||
|
|
||||||
@@ -13,7 +11,6 @@ import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
|||||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||||
import StarIcon from '@mui/icons-material/Star';
|
import StarIcon from '@mui/icons-material/Star';
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
import TuneIcon from '@mui/icons-material/Tune';
|
|
||||||
|
|
||||||
import { extractErrorMessage } from '../utils';
|
import { extractErrorMessage } from '../utils';
|
||||||
|
|
||||||
@@ -22,11 +19,9 @@ import * as EMSESP from './api';
|
|||||||
const HelpInformation: FC = () => {
|
const HelpInformation: FC = () => {
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const { me } = useContext(AuthenticatedContext);
|
|
||||||
|
|
||||||
const saveFile = (json: any, endpoint: string) => {
|
const saveFile = (json: any, endpoint: string) => {
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
const filename = 'emsesp_' + endpoint + '.json';
|
const filename = 'emsesp_' + endpoint + '.txt';
|
||||||
a.href = URL.createObjectURL(
|
a.href = URL.createObjectURL(
|
||||||
new Blob([JSON.stringify(json, null, 2)], {
|
new Blob([JSON.stringify(json, null, 2)], {
|
||||||
type: 'text/plain'
|
type: 'text/plain'
|
||||||
@@ -36,7 +31,7 @@ const HelpInformation: FC = () => {
|
|||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
enqueueSnackbar('File downloaded', { variant: 'info' });
|
enqueueSnackbar('System information downloaded', { variant: 'info' });
|
||||||
};
|
};
|
||||||
|
|
||||||
const callAPI = async (endpoint: string) => {
|
const callAPI = async (endpoint: string) => {
|
||||||
@@ -56,60 +51,27 @@ const HelpInformation: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadSettings = async () => {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.getSettings();
|
|
||||||
if (response.status !== 200) {
|
|
||||||
enqueueSnackbar('Unable to get settings', { variant: 'error' });
|
|
||||||
} else {
|
|
||||||
saveFile(response.data, 'settings');
|
|
||||||
}
|
|
||||||
} catch (error: unknown) {
|
|
||||||
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const downloadCustomizations = async () => {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.getCustomizations();
|
|
||||||
if (response.status !== 200) {
|
|
||||||
enqueueSnackbar('Unable to get customizations', { variant: 'error' });
|
|
||||||
} else {
|
|
||||||
saveFile(response.data, 'customizations');
|
|
||||||
}
|
|
||||||
} catch (error: unknown) {
|
|
||||||
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Application Information & Support" titleGutter>
|
<SectionContent title="Support Information" titleGutter>
|
||||||
<List>
|
<List>
|
||||||
<ListItem>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<TuneIcon />
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText>
|
|
||||||
For a help on each of the Application Settings see
|
|
||||||
<Link
|
|
||||||
target="_blank"
|
|
||||||
href="https://emsesp.github.io/docs/#/Configure-firmware?id=ems-esp-settings"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
{'Configuring EMS-ESP'}
|
|
||||||
</Link>
|
|
||||||
</ListItemText>
|
|
||||||
</ListItem>
|
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<MenuBookIcon />
|
<MenuBookIcon />
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
<ListItemText>
|
<ListItemText>
|
||||||
For general information about EMS-ESP visit the online
|
Visit the online
|
||||||
<Link target="_blank" href="https://emsesp.github.io/docs" color="primary">
|
<Link target="_blank" href="https://emsesp.github.io/docs" color="primary">
|
||||||
{'Documentation'}
|
{'Wiki'}
|
||||||
</Link>
|
</Link>
|
||||||
|
to get instructions on how to
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
href="https://emsesp.github.io/docs/#/Configure-firmware?id=ems-esp-settings"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{'configure'}
|
||||||
|
</Link>
|
||||||
|
EMS-ESP and access other information.
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
@@ -122,7 +84,7 @@ const HelpInformation: FC = () => {
|
|||||||
<Link target="_blank" href="https://discord.gg/3J3GgnzpyT" color="primary">
|
<Link target="_blank" href="https://discord.gg/3J3GgnzpyT" color="primary">
|
||||||
{'Discord'}
|
{'Discord'}
|
||||||
</Link>
|
</Link>
|
||||||
server
|
server.
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
@@ -130,69 +92,33 @@ const HelpInformation: FC = () => {
|
|||||||
<ListItemAvatar>
|
<ListItemAvatar>
|
||||||
<GitHubIcon />
|
<GitHubIcon />
|
||||||
</ListItemAvatar>
|
</ListItemAvatar>
|
||||||
|
|
||||||
<ListItemText>
|
<ListItemText>
|
||||||
To report an issue or request a feature, please
|
Submit a
|
||||||
<Link component="button" variant="body1" onClick={() => callAPI('info')}>
|
|
||||||
download
|
|
||||||
</Link>
|
|
||||||
the debug information and include in a new
|
|
||||||
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32/issues/new/choose" color="primary">
|
<Link target="_blank" href="https://github.com/emsesp/EMS-ESP32/issues/new/choose" color="primary">
|
||||||
GitHub issue
|
support issue
|
||||||
</Link>
|
</Link>
|
||||||
|
for requesting a new feature or reporting a bug.
|
||||||
|
<br />
|
||||||
|
Make sure you also
|
||||||
|
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => callAPI('info')}>
|
||||||
|
download
|
||||||
|
</Button>
|
||||||
|
and attach your system details for a faster response.
|
||||||
</ListItemText>
|
</ListItemText>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
{me.admin && (
|
<Box border={1} p={1} mt={4}>
|
||||||
<>
|
<Typography align="center" variant="h6" color="orange">
|
||||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
EMS-ESP will always be a free and open-source project
|
||||||
Download Settings
|
<br></br>Please consider supporting it with a
|
||||||
</Typography>
|
<StarIcon style={{ fontSize: 16, color: 'yellow', verticalAlign: 'middle' }} /> on
|
||||||
<Box color="warning.main">
|
|
||||||
<Typography variant="body2">
|
|
||||||
Export the application settings and any customizations to a JSON file. These files can later be uploaded
|
|
||||||
via System→Upload.
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ display: 'flex' }}>
|
|
||||||
<ButtonRow>
|
|
||||||
<Button
|
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => downloadSettings()}
|
|
||||||
>
|
|
||||||
settings
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<DownloadIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={() => downloadCustomizations()}
|
|
||||||
>
|
|
||||||
customizations
|
|
||||||
</Button>
|
|
||||||
</ButtonRow>
|
|
||||||
</Box>
|
|
||||||
<MessageBox
|
|
||||||
my={2}
|
|
||||||
level="warning"
|
|
||||||
message="Be careful when sharing your Settings as the file contains passwords and other sensitive system
|
|
||||||
information!"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Box bgcolor="secondary.info" border={1} p={1} mt={4}>
|
|
||||||
<Typography align="center" variant="h6">
|
|
||||||
EMS-ESP is a free and open-source project.
|
|
||||||
<br></br>Please consider supporting us by giving it a
|
|
||||||
<StarIcon style={{ fontSize: 16, color: '#fdff3a', verticalAlign: 'middle' }} /> on
|
|
||||||
<Link href="https://github.com/emsesp/EMS-ESP32" color="primary">
|
<Link href="https://github.com/emsesp/EMS-ESP32" color="primary">
|
||||||
{'GitHub'}
|
{'GitHub'}
|
||||||
</Link>
|
</Link>
|
||||||
!
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography align="center">@proddy @MichaelDvP</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</SectionContent>
|
</SectionContent>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import {
|
|||||||
ToggleButtonGroup,
|
ToggleButtonGroup,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Grid,
|
Grid,
|
||||||
TextField
|
TextField,
|
||||||
|
Link
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
|
||||||
import { Table } from '@table-library/react-table-library/table';
|
import { Table } from '@table-library/react-table-library/table';
|
||||||
@@ -26,11 +27,6 @@ import { useSnackbar } from 'notistack';
|
|||||||
import SaveIcon from '@mui/icons-material/Save';
|
import SaveIcon from '@mui/icons-material/Save';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
|
||||||
// import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
|
||||||
// import StarIcon from '@mui/icons-material/Star';
|
|
||||||
// import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
|
|
||||||
// import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
|
||||||
|
|
||||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||||
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
||||||
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
|
import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined';
|
||||||
@@ -48,13 +44,15 @@ import { extractErrorMessage } from '../utils';
|
|||||||
|
|
||||||
import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
|
import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
|
||||||
|
|
||||||
|
export const APIURL = window.location.origin + '/api/';
|
||||||
|
|
||||||
const SettingsCustomization: FC = () => {
|
const SettingsCustomization: FC = () => {
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, n: '', m: 0, w: false }]);
|
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([{ id: '', v: 0, n: '', m: 0, w: false }]);
|
||||||
const [devices, setDevices] = useState<Devices>();
|
const [devices, setDevices] = useState<Devices>();
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
const [selectedDevice, setSelectedDevice] = useState<number>(0);
|
const [selectedDevice, setSelectedDevice] = useState<number>(-1);
|
||||||
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
||||||
const [selectedFilters, setSelectedFilters] = useState<number>(0);
|
const [selectedFilters, setSelectedFilters] = useState<number>(0);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
@@ -63,80 +61,59 @@ const SettingsCustomization: FC = () => {
|
|||||||
const [masks, setMasks] = useState(() => ['']);
|
const [masks, setMasks] = useState(() => ['']);
|
||||||
|
|
||||||
const entities_theme = useTheme({
|
const entities_theme = useTheme({
|
||||||
|
Table: `
|
||||||
|
--data-table-library_grid-template-columns: 120px repeat(1, minmax(0, 1fr)) 120px;
|
||||||
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: white;
|
.td {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
min-height: 32px;
|
}
|
||||||
|
`,
|
||||||
|
BaseCell: `
|
||||||
|
&:last-of-type {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
|
||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
font-weight: 500;
|
|
||||||
|
.th {
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-of-type(1) .th {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
Row: `
|
Row: `
|
||||||
background-color: #1e1e1e;
|
background-color: #1e1e1e;
|
||||||
border-top: 1px solid #565656;
|
|
||||||
border-bottom: 1px solid #565656;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
|
||||||
&:not(:last-of-type) {
|
.td {
|
||||||
margin-bottom: -1px;
|
border-top: 1px solid #565656;
|
||||||
|
border-bottom: 1px solid #565656;
|
||||||
}
|
}
|
||||||
&:not(:first-of-type) {
|
|
||||||
margin-top: -1px;
|
&.tr.tr-body.row-select.row-select-single-selected {
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
z-index: 2;
|
|
||||||
color: white;
|
|
||||||
border-top: 1px solid #177ac9;
|
|
||||||
border-bottom: 1px solid #177ac9;
|
|
||||||
},
|
|
||||||
&.tr.tr-body.row-select.row-select-single-selected, &.tr.tr-body.row-select.row-select-selected {
|
|
||||||
background-color: #3d4752;
|
background-color: #3d4752;
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
z-index: 2;
|
}
|
||||||
border-top: 1px solid #177ac9;
|
|
||||||
border-bottom: 1px solid #177ac9;
|
&:nth-of-type(odd) .td {
|
||||||
|
background-color: #303030;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
BaseCell: `
|
Cell: `
|
||||||
border-top: 1px solid transparent;
|
|
||||||
border-right: 1px solid transparent;
|
|
||||||
border-bottom: 1px solid transparent;
|
|
||||||
&:not(.stiff) > div {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
width: 120px;
|
|
||||||
min-width: 120px;
|
|
||||||
max-width: 120px;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
&:nth-of-type(2) {
|
||||||
padding-left: 8px;
|
padding: 8px;
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
&:nth-of-type(3) {
|
&:last-of-type {
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
text-align: right;
|
|
||||||
width: 120px;
|
|
||||||
min-width: 120px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
HeaderCell: `
|
|
||||||
&:nth-of-type(1) {
|
|
||||||
padding-left: 24px;
|
|
||||||
}
|
|
||||||
&:nth-of-type(2) {
|
|
||||||
padding-left: 0px;
|
|
||||||
}
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
border-right: 1px solid #565656;
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
@@ -209,7 +186,15 @@ const SettingsCustomization: FC = () => {
|
|||||||
} else if (de.n === '') {
|
} else if (de.n === '') {
|
||||||
return 'Command: ' + de.id;
|
return 'Command: ' + de.id;
|
||||||
}
|
}
|
||||||
return de.n + ' (' + de.id + ')';
|
return (
|
||||||
|
<>
|
||||||
|
{de.n} (
|
||||||
|
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
||||||
|
{de.id}
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMaskNumber = (newMask: string[]) => {
|
const getMaskNumber = (newMask: string[]) => {
|
||||||
@@ -254,20 +239,12 @@ const SettingsCustomization: FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function compareDevices(a: DeviceShort, b: DeviceShort) {
|
|
||||||
if (a.s < b.s) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.s > b.s) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeSelectedDevice = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const changeSelectedDevice = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const selected_device = parseInt(event.target.value, 10);
|
if (devices) {
|
||||||
setSelectedDevice(selected_device);
|
const selected_device = parseInt(event.target.value, 10);
|
||||||
fetchDeviceEntities(selected_device);
|
setSelectedDevice(selected_device);
|
||||||
|
fetchDeviceEntities(devices?.devices[selected_device].i);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetCustomization = async () => {
|
const resetCustomization = async () => {
|
||||||
@@ -282,7 +259,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveCustomization = async () => {
|
const saveCustomization = async () => {
|
||||||
if (deviceEntities && selectedDevice) {
|
if (devices && deviceEntities && selectedDevice !== -1) {
|
||||||
const masked_entities = deviceEntities
|
const masked_entities = deviceEntities
|
||||||
.filter((de) => de.m !== de.om)
|
.filter((de) => de.m !== de.om)
|
||||||
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.id);
|
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.id);
|
||||||
@@ -294,7 +271,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await EMSESP.writeMaskedEntities({
|
const response = await EMSESP.writeMaskedEntities({
|
||||||
id: selectedDevice,
|
id: devices?.devices[selectedDevice].i,
|
||||||
entity_ids: masked_entities
|
entity_ids: masked_entities
|
||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -320,13 +297,13 @@ const SettingsCustomization: FC = () => {
|
|||||||
<Typography variant="body2">Select a device and customize each of its entities using the options:</Typography>
|
<Typography variant="body2">Select a device and customize each of its entities using the options:</Typography>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
<OptionIcon type="favorite" isSet={true} />
|
<OptionIcon type="favorite" isSet={true} />
|
||||||
=mark as a favorite
|
=mark as favorite
|
||||||
<OptionIcon type="readonly" isSet={true} />
|
<OptionIcon type="readonly" isSet={true} />
|
||||||
=disable write action
|
=disable write action
|
||||||
<OptionIcon type="api_mqtt_exclude" isSet={true} />
|
<OptionIcon type="api_mqtt_exclude" isSet={true} />
|
||||||
=exclude from MQTT and API outputs
|
=exclude from MQTT and API
|
||||||
<OptionIcon type="web_exclude" isSet={true} />
|
<OptionIcon type="web_exclude" isSet={true} />
|
||||||
=hide from Web Dashboard
|
=hide from Dashboard
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
@@ -339,11 +316,11 @@ const SettingsCustomization: FC = () => {
|
|||||||
margin="normal"
|
margin="normal"
|
||||||
select
|
select
|
||||||
>
|
>
|
||||||
<MenuItem disabled key={0} value={0}>
|
<MenuItem disabled key={0} value={-1}>
|
||||||
Select a device...
|
Select a device...
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{devices.devices.sort(compareDevices).map((device: DeviceShort, index) => (
|
{devices.devices.map((device: DeviceShort, index) => (
|
||||||
<MenuItem key={index} value={device.i}>
|
<MenuItem key={index} value={index}>
|
||||||
{device.s}
|
{device.s}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
@@ -451,7 +428,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell>OPTIONS</HeaderCell>
|
<HeaderCell stiff>OPTIONS</HeaderCell>
|
||||||
<HeaderCell resize>
|
<HeaderCell resize>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -462,13 +439,13 @@ const SettingsCustomization: FC = () => {
|
|||||||
NAME
|
NAME
|
||||||
</Button>
|
</Button>
|
||||||
</HeaderCell>
|
</HeaderCell>
|
||||||
<HeaderCell>VALUE</HeaderCell>
|
<HeaderCell resize>VALUE</HeaderCell>
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((de: DeviceEntity) => (
|
{tableList.map((de: DeviceEntity) => (
|
||||||
<Row key={de.id} item={de}>
|
<Row key={de.id} item={de}>
|
||||||
<Cell>
|
<Cell stiff>
|
||||||
<ToggleButtonGroup
|
<ToggleButtonGroup
|
||||||
size="small"
|
size="small"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ export interface Settings {
|
|||||||
syslog_mark_interval: number;
|
syslog_mark_interval: number;
|
||||||
syslog_host: string;
|
syslog_host: string;
|
||||||
syslog_port: number;
|
syslog_port: number;
|
||||||
master_thermostat: number;
|
|
||||||
shower_timer: boolean;
|
shower_timer: boolean;
|
||||||
shower_alert: boolean;
|
shower_alert: boolean;
|
||||||
shower_alert_coldshot: number;
|
shower_alert_coldshot: number;
|
||||||
@@ -98,6 +97,7 @@ export interface SensorData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CoreData {
|
export interface CoreData {
|
||||||
|
connected: boolean;
|
||||||
devices: Device[];
|
devices: Device[];
|
||||||
active_sensors: number;
|
active_sensors: number;
|
||||||
analog_enabled: boolean;
|
analog_enabled: boolean;
|
||||||
@@ -105,9 +105,10 @@ export interface CoreData {
|
|||||||
|
|
||||||
export interface DeviceShort {
|
export interface DeviceShort {
|
||||||
i: number; // id
|
i: number; // id
|
||||||
d: number; // deviceid
|
d?: number; // deviceid
|
||||||
p: number; // productid
|
p?: number; // productid
|
||||||
s: string; // shortname
|
s: string; // shortname
|
||||||
|
t?: string; // device type name
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Devices {
|
export interface Devices {
|
||||||
|
|||||||
@@ -5,4 +5,3 @@ export * from './submit';
|
|||||||
export * from './time';
|
export * from './time';
|
||||||
export * from './useRest';
|
export * from './useRest';
|
||||||
export * from './props';
|
export * from './props';
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ static bool getMD5(uint8_t * data, uint16_t len, char * output){//33 bytes or mo
|
|||||||
memset(_buf, 0x00, 16);
|
memset(_buf, 0x00, 16);
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
mbedtls_md5_init(&_ctx);
|
mbedtls_md5_init(&_ctx);
|
||||||
mbedtls_md5_starts(&_ctx);
|
mbedtls_md5_update_ret (&_ctx,data,len);
|
||||||
mbedtls_md5_update(&_ctx, data, len);
|
mbedtls_md5_finish_ret(&_ctx,data);
|
||||||
mbedtls_md5_finish(&_ctx, _buf);
|
mbedtls_internal_md5_process( &_ctx ,data);
|
||||||
#else
|
#else
|
||||||
MD5Init(&_ctx);
|
MD5Init(&_ctx);
|
||||||
MD5Update(&_ctx, data, len);
|
MD5Update(&_ctx, data, len);
|
||||||
|
|||||||
@@ -1,339 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
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
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
Copyright 2020 Brian Pugh
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
Copyright (c) 2017, Arm Limited. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
- Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
- Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
- Neither the name of ARM nor the names of its contributors may be used to
|
|
||||||
endorse or promote products derived from this software without specific prior
|
|
||||||
written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
static constexpr const char LFS_NAME[] = "spiffs";
|
|
||||||
|
|
||||||
#include "vfs_api.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include "esp_littlefs.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "LITTLEFS.h"
|
|
||||||
|
|
||||||
using namespace fs;
|
|
||||||
|
|
||||||
LITTLEFSFS::LITTLEFSFS() : FS(FSImplPtr(new VFSImpl()))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LITTLEFSFS::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles)
|
|
||||||
{
|
|
||||||
if(esp_littlefs_mounted(LFS_NAME)){
|
|
||||||
log_w("LITTLEFS Already Mounted!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_vfs_littlefs_conf_t conf = {
|
|
||||||
.base_path = basePath,
|
|
||||||
.partition_label = LFS_NAME,
|
|
||||||
.format_if_mount_failed = false
|
|
||||||
};
|
|
||||||
|
|
||||||
esp_err_t err = esp_vfs_littlefs_register(&conf);
|
|
||||||
if(err == ESP_FAIL && formatOnFail){
|
|
||||||
if(format()){
|
|
||||||
err = esp_vfs_littlefs_register(&conf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(err != ESP_OK){
|
|
||||||
log_e("Mounting LITTLEFS failed! Error: %d", err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_impl->mountpoint(basePath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LITTLEFSFS::end()
|
|
||||||
{
|
|
||||||
if(esp_littlefs_mounted(LFS_NAME)){
|
|
||||||
esp_err_t err = esp_vfs_littlefs_unregister(LFS_NAME);
|
|
||||||
if(err){
|
|
||||||
log_e("Unmounting LITTLEFS failed! Error: %d", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_impl->mountpoint(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LITTLEFSFS::format()
|
|
||||||
{
|
|
||||||
disableCore0WDT();
|
|
||||||
esp_err_t err = esp_littlefs_format(LFS_NAME);
|
|
||||||
enableCore0WDT();
|
|
||||||
if(err){
|
|
||||||
log_e("Formatting LITTLEFS failed! Error: %d", err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t LITTLEFSFS::totalBytes()
|
|
||||||
{
|
|
||||||
size_t total,used;
|
|
||||||
if(esp_littlefs_info(LFS_NAME, &total, &used)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t LITTLEFSFS::usedBytes()
|
|
||||||
{
|
|
||||||
size_t total,used;
|
|
||||||
if(esp_littlefs_info(LFS_NAME, &total, &used)){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return used;
|
|
||||||
}
|
|
||||||
|
|
||||||
LITTLEFSFS LITTLEFS;
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
#ifndef _LITTLEFS_H_
|
|
||||||
#define _LITTLEFS_H_
|
|
||||||
|
|
||||||
#include "FS.h"
|
|
||||||
|
|
||||||
namespace fs
|
|
||||||
{
|
|
||||||
|
|
||||||
class LITTLEFSFS : public FS
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LITTLEFSFS();
|
|
||||||
bool begin(bool formatOnFail=false, const char * basePath="/littlefs", uint8_t maxOpenFiles=5);
|
|
||||||
bool format();
|
|
||||||
size_t totalBytes();
|
|
||||||
size_t usedBytes();
|
|
||||||
void end();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fs::LITTLEFSFS LITTLEFS;
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
|||||||
#ifndef ESP_LITTLEFS_H__
|
|
||||||
#define ESP_LITTLEFS_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <utime.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/reent.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#include "lfs.h" //#include "littlefs/lfs.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Last Modified Time
|
|
||||||
*
|
|
||||||
* Use 't' for LITTLEFS_ATTR_MTIME to match example:
|
|
||||||
* https://github.com/ARMmbed/littlefs/issues/23#issuecomment-482293539
|
|
||||||
* And to match other external tools such as:
|
|
||||||
* https://github.com/earlephilhower/mklittlefs
|
|
||||||
*/
|
|
||||||
#define LITTLEFS_ATTR_MTIME ((uint8_t) 't')
|
|
||||||
|
|
||||||
/**
|
|
||||||
*Configuration structure for esp_vfs_littlefs_register.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
const char *base_path; /**< Mounting point. */
|
|
||||||
const char *partition_label; /**< Label of partition to use. */
|
|
||||||
uint8_t format_if_mount_failed:1; /**< Format the file system if it fails to mount. */
|
|
||||||
uint8_t dont_mount:1; /**< Don't attempt to mount or format. Overrides format_if_mount_failed */
|
|
||||||
} esp_vfs_littlefs_conf_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register and mount littlefs to VFS with given path prefix.
|
|
||||||
*
|
|
||||||
* @param conf Pointer to esp_vfs_littlefs_conf_t configuration structure
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK if success
|
|
||||||
* - ESP_ERR_NO_MEM if objects could not be allocated
|
|
||||||
* - ESP_ERR_INVALID_STATE if already mounted or partition is encrypted
|
|
||||||
* - ESP_ERR_NOT_FOUND if partition for littlefs was not found
|
|
||||||
* - ESP_FAIL if mount or format fails
|
|
||||||
*/
|
|
||||||
esp_err_t esp_vfs_littlefs_register(const esp_vfs_littlefs_conf_t * conf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister and unmount littlefs from VFS
|
|
||||||
*
|
|
||||||
* @param partition_label Label of the partition to unregister.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK if successful
|
|
||||||
* - ESP_ERR_INVALID_STATE already unregistered
|
|
||||||
*/
|
|
||||||
esp_err_t esp_vfs_littlefs_unregister(const char* partition_label);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if littlefs is mounted
|
|
||||||
*
|
|
||||||
* @param partition_label Label of the partition to check.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - true if mounted
|
|
||||||
* - false if not mounted
|
|
||||||
*/
|
|
||||||
bool esp_littlefs_mounted(const char* partition_label);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format the littlefs partition
|
|
||||||
*
|
|
||||||
* @param partition_label Label of the partition to format.
|
|
||||||
* @return
|
|
||||||
* - ESP_OK if successful
|
|
||||||
* - ESP_FAIL on error
|
|
||||||
*/
|
|
||||||
esp_err_t esp_littlefs_format(const char* partition_label);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get information for littlefs
|
|
||||||
*
|
|
||||||
* @param partition_label Optional, label of the partition to get info for.
|
|
||||||
* @param[out] total_bytes Size of the file system
|
|
||||||
* @param[out] used_bytes Current used bytes in the file system
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK if success
|
|
||||||
* - ESP_ERR_INVALID_STATE if not mounted
|
|
||||||
*/
|
|
||||||
esp_err_t esp_littlefs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes);
|
|
||||||
|
|
||||||
#if CONFIG_LITTLEFS_HUMAN_READABLE
|
|
||||||
/**
|
|
||||||
* @brief converts an enumerated lfs error into a string.
|
|
||||||
* @param lfs_errno The enumerated littlefs error.
|
|
||||||
*/
|
|
||||||
const char * esp_littlefs_errno(enum lfs_error lfs_errno);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,695 +0,0 @@
|
|||||||
/*
|
|
||||||
* The little filesystem
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
#ifndef LFS_H
|
|
||||||
#define LFS_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "lfs_util.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/// Version info ///
|
|
||||||
|
|
||||||
// Software library version
|
|
||||||
// Major (top-nibble), incremented on backwards incompatible changes
|
|
||||||
// Minor (bottom-nibble), incremented on feature additions
|
|
||||||
#define LFS_VERSION 0x00020004
|
|
||||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
|
||||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
|
||||||
|
|
||||||
// Version of On-disk data structures
|
|
||||||
// Major (top-nibble), incremented on backwards incompatible changes
|
|
||||||
// Minor (bottom-nibble), incremented on feature additions
|
|
||||||
#define LFS_DISK_VERSION 0x00020000
|
|
||||||
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
|
||||||
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
|
||||||
|
|
||||||
|
|
||||||
/// Definitions ///
|
|
||||||
|
|
||||||
// Type definitions
|
|
||||||
typedef uint32_t lfs_size_t;
|
|
||||||
typedef uint32_t lfs_off_t;
|
|
||||||
|
|
||||||
typedef int32_t lfs_ssize_t;
|
|
||||||
typedef int32_t lfs_soff_t;
|
|
||||||
|
|
||||||
typedef uint32_t lfs_block_t;
|
|
||||||
|
|
||||||
// Maximum name size in bytes, may be redefined to reduce the size of the
|
|
||||||
// info struct. Limited to <= 1022. Stored in superblock and must be
|
|
||||||
// respected by other littlefs drivers.
|
|
||||||
#ifndef LFS_NAME_MAX
|
|
||||||
#define LFS_NAME_MAX 255
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Maximum size of a file in bytes, may be redefined to limit to support other
|
|
||||||
// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
|
|
||||||
// functions lfs_file_seek, lfs_file_size, and lfs_file_tell will return
|
|
||||||
// incorrect values due to using signed integers. Stored in superblock and
|
|
||||||
// must be respected by other littlefs drivers.
|
|
||||||
#ifndef LFS_FILE_MAX
|
|
||||||
#define LFS_FILE_MAX 2147483647
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Maximum size of custom attributes in bytes, may be redefined, but there is
|
|
||||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
|
|
||||||
#ifndef LFS_ATTR_MAX
|
|
||||||
#define LFS_ATTR_MAX 1022
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Possible error codes, these are negative to allow
|
|
||||||
// valid positive return values
|
|
||||||
enum lfs_error {
|
|
||||||
LFS_ERR_OK = 0, // No error
|
|
||||||
LFS_ERR_IO = -5, // Error during device operation
|
|
||||||
LFS_ERR_CORRUPT = -84, // Corrupted
|
|
||||||
LFS_ERR_NOENT = -2, // No directory entry
|
|
||||||
LFS_ERR_EXIST = -17, // Entry already exists
|
|
||||||
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
|
||||||
LFS_ERR_ISDIR = -21, // Entry is a dir
|
|
||||||
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
|
||||||
LFS_ERR_BADF = -9, // Bad file number
|
|
||||||
LFS_ERR_FBIG = -27, // File too large
|
|
||||||
LFS_ERR_INVAL = -22, // Invalid parameter
|
|
||||||
LFS_ERR_NOSPC = -28, // No space left on device
|
|
||||||
LFS_ERR_NOMEM = -12, // No more memory available
|
|
||||||
LFS_ERR_NOATTR = -61, // No data/attr available
|
|
||||||
LFS_ERR_NAMETOOLONG = -36, // File name too long
|
|
||||||
};
|
|
||||||
|
|
||||||
// File types
|
|
||||||
enum lfs_type {
|
|
||||||
// file types
|
|
||||||
LFS_TYPE_REG = 0x001,
|
|
||||||
LFS_TYPE_DIR = 0x002,
|
|
||||||
|
|
||||||
// internally used types
|
|
||||||
LFS_TYPE_SPLICE = 0x400,
|
|
||||||
LFS_TYPE_NAME = 0x000,
|
|
||||||
LFS_TYPE_STRUCT = 0x200,
|
|
||||||
LFS_TYPE_USERATTR = 0x300,
|
|
||||||
LFS_TYPE_FROM = 0x100,
|
|
||||||
LFS_TYPE_TAIL = 0x600,
|
|
||||||
LFS_TYPE_GLOBALS = 0x700,
|
|
||||||
LFS_TYPE_CRC = 0x500,
|
|
||||||
|
|
||||||
// internally used type specializations
|
|
||||||
LFS_TYPE_CREATE = 0x401,
|
|
||||||
LFS_TYPE_DELETE = 0x4ff,
|
|
||||||
LFS_TYPE_SUPERBLOCK = 0x0ff,
|
|
||||||
LFS_TYPE_DIRSTRUCT = 0x200,
|
|
||||||
LFS_TYPE_CTZSTRUCT = 0x202,
|
|
||||||
LFS_TYPE_INLINESTRUCT = 0x201,
|
|
||||||
LFS_TYPE_SOFTTAIL = 0x600,
|
|
||||||
LFS_TYPE_HARDTAIL = 0x601,
|
|
||||||
LFS_TYPE_MOVESTATE = 0x7ff,
|
|
||||||
|
|
||||||
// internal chip sources
|
|
||||||
LFS_FROM_NOOP = 0x000,
|
|
||||||
LFS_FROM_MOVE = 0x101,
|
|
||||||
LFS_FROM_USERATTRS = 0x102,
|
|
||||||
};
|
|
||||||
|
|
||||||
// File open flags
|
|
||||||
enum lfs_open_flags {
|
|
||||||
// open flags
|
|
||||||
LFS_O_RDONLY = 1, // Open a file as read only
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
LFS_O_WRONLY = 2, // Open a file as write only
|
|
||||||
LFS_O_RDWR = 3, // Open a file as read and write
|
|
||||||
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
|
||||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
|
||||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
|
||||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// internally used flags
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
LFS_F_DIRTY = 0x010000, // File does not match storage
|
|
||||||
LFS_F_WRITING = 0x020000, // File has been written since last flush
|
|
||||||
#endif
|
|
||||||
LFS_F_READING = 0x040000, // File has been read since last flush
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
LFS_F_ERRED = 0x080000, // An error occurred during write
|
|
||||||
#endif
|
|
||||||
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
|
|
||||||
};
|
|
||||||
|
|
||||||
// File seek flags
|
|
||||||
enum lfs_whence_flags {
|
|
||||||
LFS_SEEK_SET = 0, // Seek relative to an absolute position
|
|
||||||
LFS_SEEK_CUR = 1, // Seek relative to the current file position
|
|
||||||
LFS_SEEK_END = 2, // Seek relative to the end of the file
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Configuration provided during initialization of the littlefs
|
|
||||||
struct lfs_config {
|
|
||||||
// Opaque user provided context that can be used to pass
|
|
||||||
// information to the block device operations
|
|
||||||
void *context;
|
|
||||||
|
|
||||||
// Read a region in a block. Negative error codes are propogated
|
|
||||||
// to the user.
|
|
||||||
int (*read)(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
// Program a region in a block. The block must have previously
|
|
||||||
// been erased. Negative error codes are propogated to the user.
|
|
||||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
||||||
int (*prog)(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
// Erase a block. A block must be erased before being programmed.
|
|
||||||
// The state of an erased block is undefined. Negative error codes
|
|
||||||
// are propogated to the user.
|
|
||||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
||||||
int (*erase)(const struct lfs_config *c, lfs_block_t block);
|
|
||||||
|
|
||||||
// Sync the state of the underlying block device. Negative error codes
|
|
||||||
// are propogated to the user.
|
|
||||||
int (*sync)(const struct lfs_config *c);
|
|
||||||
|
|
||||||
#ifdef LFS_THREADSAFE
|
|
||||||
// Lock the underlying block device. Negative error codes
|
|
||||||
// are propogated to the user.
|
|
||||||
int (*lock)(const struct lfs_config *c);
|
|
||||||
|
|
||||||
// Unlock the underlying block device. Negative error codes
|
|
||||||
// are propogated to the user.
|
|
||||||
int (*unlock)(const struct lfs_config *c);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Minimum size of a block read. All read operations will be a
|
|
||||||
// multiple of this value.
|
|
||||||
lfs_size_t read_size;
|
|
||||||
|
|
||||||
// Minimum size of a block program. All program operations will be a
|
|
||||||
// multiple of this value.
|
|
||||||
lfs_size_t prog_size;
|
|
||||||
|
|
||||||
// Size of an erasable block. This does not impact ram consumption and
|
|
||||||
// may be larger than the physical erase size. However, non-inlined files
|
|
||||||
// take up at minimum one block. Must be a multiple of the read
|
|
||||||
// and program sizes.
|
|
||||||
lfs_size_t block_size;
|
|
||||||
|
|
||||||
// Number of erasable blocks on the device.
|
|
||||||
lfs_size_t block_count;
|
|
||||||
|
|
||||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
|
||||||
// the metadata to another block. Suggested values are in the
|
|
||||||
// range 100-1000, with large values having better performance at the cost
|
|
||||||
// of less consistent wear distribution.
|
|
||||||
//
|
|
||||||
// Set to -1 to disable block-level wear-leveling.
|
|
||||||
int32_t block_cycles;
|
|
||||||
|
|
||||||
// Size of block caches. Each cache buffers a portion of a block in RAM.
|
|
||||||
// The littlefs needs a read cache, a program cache, and one additional
|
|
||||||
// cache per file. Larger caches can improve performance by storing more
|
|
||||||
// data and reducing the number of disk accesses. Must be a multiple of
|
|
||||||
// the read and program sizes, and a factor of the block size.
|
|
||||||
lfs_size_t cache_size;
|
|
||||||
|
|
||||||
// Size of the lookahead buffer in bytes. A larger lookahead buffer
|
|
||||||
// increases the number of blocks found during an allocation pass. The
|
|
||||||
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
|
|
||||||
// can track 8 blocks. Must be a multiple of 8.
|
|
||||||
lfs_size_t lookahead_size;
|
|
||||||
|
|
||||||
// Optional statically allocated read buffer. Must be cache_size.
|
|
||||||
// By default lfs_malloc is used to allocate this buffer.
|
|
||||||
void *read_buffer;
|
|
||||||
|
|
||||||
// Optional statically allocated program buffer. Must be cache_size.
|
|
||||||
// By default lfs_malloc is used to allocate this buffer.
|
|
||||||
void *prog_buffer;
|
|
||||||
|
|
||||||
// Optional statically allocated lookahead buffer. Must be lookahead_size
|
|
||||||
// and aligned to a 32-bit boundary. By default lfs_malloc is used to
|
|
||||||
// allocate this buffer.
|
|
||||||
void *lookahead_buffer;
|
|
||||||
|
|
||||||
// Optional upper limit on length of file names in bytes. No downside for
|
|
||||||
// larger names except the size of the info struct which is controlled by
|
|
||||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
|
|
||||||
// superblock and must be respected by other littlefs drivers.
|
|
||||||
lfs_size_t name_max;
|
|
||||||
|
|
||||||
// Optional upper limit on files in bytes. No downside for larger files
|
|
||||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
|
|
||||||
// in superblock and must be respected by other littlefs drivers.
|
|
||||||
lfs_size_t file_max;
|
|
||||||
|
|
||||||
// Optional upper limit on custom attributes in bytes. No downside for
|
|
||||||
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
|
|
||||||
// LFS_ATTR_MAX when zero.
|
|
||||||
lfs_size_t attr_max;
|
|
||||||
|
|
||||||
// Optional upper limit on total space given to metadata pairs in bytes. On
|
|
||||||
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
|
|
||||||
// can help bound the metadata compaction time. Must be <= block_size.
|
|
||||||
// Defaults to block_size when zero.
|
|
||||||
lfs_size_t metadata_max;
|
|
||||||
};
|
|
||||||
|
|
||||||
// File info structure
|
|
||||||
struct lfs_info {
|
|
||||||
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
|
||||||
uint8_t type;
|
|
||||||
|
|
||||||
// Size of the file, only valid for REG files. Limited to 32-bits.
|
|
||||||
lfs_size_t size;
|
|
||||||
|
|
||||||
// Name of the file stored as a null-terminated string. Limited to
|
|
||||||
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
|
|
||||||
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
|
|
||||||
// respected by other littlefs drivers.
|
|
||||||
char name[LFS_NAME_MAX+1];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Custom attribute structure, used to describe custom attributes
|
|
||||||
// committed atomically during file writes.
|
|
||||||
struct lfs_attr {
|
|
||||||
// 8-bit type of attribute, provided by user and used to
|
|
||||||
// identify the attribute
|
|
||||||
uint8_t type;
|
|
||||||
|
|
||||||
// Pointer to buffer containing the attribute
|
|
||||||
void *buffer;
|
|
||||||
|
|
||||||
// Size of attribute in bytes, limited to LFS_ATTR_MAX
|
|
||||||
lfs_size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Optional configuration provided during lfs_file_opencfg
|
|
||||||
struct lfs_file_config {
|
|
||||||
// Optional statically allocated file buffer. Must be cache_size.
|
|
||||||
// By default lfs_malloc is used to allocate this buffer.
|
|
||||||
void *buffer;
|
|
||||||
|
|
||||||
// Optional list of custom attributes related to the file. If the file
|
|
||||||
// is opened with read access, these attributes will be read from disk
|
|
||||||
// during the open call. If the file is opened with write access, the
|
|
||||||
// attributes will be written to disk every file sync or close. This
|
|
||||||
// write occurs atomically with update to the file's contents.
|
|
||||||
//
|
|
||||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
|
||||||
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
|
|
||||||
// than the buffer, it will be padded with zeros. If the stored attribute
|
|
||||||
// is larger, then it will be silently truncated. If the attribute is not
|
|
||||||
// found, it will be created implicitly.
|
|
||||||
struct lfs_attr *attrs;
|
|
||||||
|
|
||||||
// Number of custom attributes in the list
|
|
||||||
lfs_size_t attr_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// internal littlefs data structures ///
|
|
||||||
typedef struct lfs_cache {
|
|
||||||
lfs_block_t block;
|
|
||||||
lfs_off_t off;
|
|
||||||
lfs_size_t size;
|
|
||||||
uint8_t *buffer;
|
|
||||||
} lfs_cache_t;
|
|
||||||
|
|
||||||
typedef struct lfs_mdir {
|
|
||||||
lfs_block_t pair[2];
|
|
||||||
uint32_t rev;
|
|
||||||
lfs_off_t off;
|
|
||||||
uint32_t etag;
|
|
||||||
uint16_t count;
|
|
||||||
bool erased;
|
|
||||||
bool split;
|
|
||||||
lfs_block_t tail[2];
|
|
||||||
} lfs_mdir_t;
|
|
||||||
|
|
||||||
// littlefs directory type
|
|
||||||
typedef struct lfs_dir {
|
|
||||||
struct lfs_dir *next;
|
|
||||||
uint16_t id;
|
|
||||||
uint8_t type;
|
|
||||||
lfs_mdir_t m;
|
|
||||||
|
|
||||||
lfs_off_t pos;
|
|
||||||
lfs_block_t head[2];
|
|
||||||
} lfs_dir_t;
|
|
||||||
|
|
||||||
// littlefs file type
|
|
||||||
typedef struct lfs_file {
|
|
||||||
struct lfs_file *next;
|
|
||||||
uint16_t id;
|
|
||||||
uint8_t type;
|
|
||||||
lfs_mdir_t m;
|
|
||||||
|
|
||||||
struct lfs_ctz {
|
|
||||||
lfs_block_t head;
|
|
||||||
lfs_size_t size;
|
|
||||||
} ctz;
|
|
||||||
|
|
||||||
uint32_t flags;
|
|
||||||
lfs_off_t pos;
|
|
||||||
lfs_block_t block;
|
|
||||||
lfs_off_t off;
|
|
||||||
lfs_cache_t cache;
|
|
||||||
|
|
||||||
const struct lfs_file_config *cfg;
|
|
||||||
} lfs_file_t;
|
|
||||||
|
|
||||||
typedef struct lfs_superblock {
|
|
||||||
uint32_t version;
|
|
||||||
lfs_size_t block_size;
|
|
||||||
lfs_size_t block_count;
|
|
||||||
lfs_size_t name_max;
|
|
||||||
lfs_size_t file_max;
|
|
||||||
lfs_size_t attr_max;
|
|
||||||
} lfs_superblock_t;
|
|
||||||
|
|
||||||
typedef struct lfs_gstate {
|
|
||||||
uint32_t tag;
|
|
||||||
lfs_block_t pair[2];
|
|
||||||
} lfs_gstate_t;
|
|
||||||
|
|
||||||
// The littlefs filesystem type
|
|
||||||
typedef struct lfs {
|
|
||||||
lfs_cache_t rcache;
|
|
||||||
lfs_cache_t pcache;
|
|
||||||
|
|
||||||
lfs_block_t root[2];
|
|
||||||
struct lfs_mlist {
|
|
||||||
struct lfs_mlist *next;
|
|
||||||
uint16_t id;
|
|
||||||
uint8_t type;
|
|
||||||
lfs_mdir_t m;
|
|
||||||
} *mlist;
|
|
||||||
uint32_t seed;
|
|
||||||
|
|
||||||
lfs_gstate_t gstate;
|
|
||||||
lfs_gstate_t gdisk;
|
|
||||||
lfs_gstate_t gdelta;
|
|
||||||
|
|
||||||
struct lfs_free {
|
|
||||||
lfs_block_t off;
|
|
||||||
lfs_block_t size;
|
|
||||||
lfs_block_t i;
|
|
||||||
lfs_block_t ack;
|
|
||||||
uint32_t *buffer;
|
|
||||||
} free;
|
|
||||||
|
|
||||||
const struct lfs_config *cfg;
|
|
||||||
lfs_size_t name_max;
|
|
||||||
lfs_size_t file_max;
|
|
||||||
lfs_size_t attr_max;
|
|
||||||
|
|
||||||
#ifdef LFS_MIGRATE
|
|
||||||
struct lfs1 *lfs1;
|
|
||||||
#endif
|
|
||||||
} lfs_t;
|
|
||||||
|
|
||||||
|
|
||||||
/// Filesystem functions ///
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Format a block device with the littlefs
|
|
||||||
//
|
|
||||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
|
||||||
// object, and does not leave the filesystem mounted. The config struct must
|
|
||||||
// be zeroed for defaults and backwards compatibility.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Mounts a littlefs
|
|
||||||
//
|
|
||||||
// Requires a littlefs object and config struct. Multiple filesystems
|
|
||||||
// may be mounted simultaneously with multiple littlefs objects. Both
|
|
||||||
// lfs and config must be allocated while mounted. The config struct must
|
|
||||||
// be zeroed for defaults and backwards compatibility.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
|
||||||
|
|
||||||
// Unmounts a littlefs
|
|
||||||
//
|
|
||||||
// Does nothing besides releasing any allocated resources.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_unmount(lfs_t *lfs);
|
|
||||||
|
|
||||||
/// General operations ///
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Removes a file or directory
|
|
||||||
//
|
|
||||||
// If removing a directory, the directory must be empty.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_remove(lfs_t *lfs, const char *path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Rename or move a file or directory
|
|
||||||
//
|
|
||||||
// If the destination exists, it must match the source in type.
|
|
||||||
// If the destination is a directory, the directory must be empty.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Find info about a file or directory
|
|
||||||
//
|
|
||||||
// Fills out the info structure, based on the specified file or directory.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
|
||||||
|
|
||||||
// Get a custom attribute
|
|
||||||
//
|
|
||||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
|
||||||
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
|
|
||||||
// the buffer, it will be padded with zeros. If the stored attribute is larger,
|
|
||||||
// then it will be silently truncated. If no attribute is found, the error
|
|
||||||
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
|
|
||||||
//
|
|
||||||
// Returns the size of the attribute, or a negative error code on failure.
|
|
||||||
// Note, the returned size is the size of the attribute on disk, irrespective
|
|
||||||
// of the size of the buffer. This can be used to dynamically allocate a buffer
|
|
||||||
// or check for existance.
|
|
||||||
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
|
||||||
uint8_t type, void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Set custom attributes
|
|
||||||
//
|
|
||||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
|
||||||
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
|
|
||||||
// implicitly created.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_setattr(lfs_t *lfs, const char *path,
|
|
||||||
uint8_t type, const void *buffer, lfs_size_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Removes a custom attribute
|
|
||||||
//
|
|
||||||
// If an attribute is not found, nothing happens.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/// File operations ///
|
|
||||||
|
|
||||||
// Open a file
|
|
||||||
//
|
|
||||||
// The mode that the file is opened in is determined by the flags, which
|
|
||||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
const char *path, int flags);
|
|
||||||
|
|
||||||
// Open a file with extra configuration
|
|
||||||
//
|
|
||||||
// The mode that the file is opened in is determined by the flags, which
|
|
||||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
|
||||||
//
|
|
||||||
// The config struct provides additional config options per file as described
|
|
||||||
// above. The config struct must be allocated while the file is open, and the
|
|
||||||
// config struct must be zeroed for defaults and backwards compatibility.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
const char *path, int flags,
|
|
||||||
const struct lfs_file_config *config);
|
|
||||||
|
|
||||||
// Close a file
|
|
||||||
//
|
|
||||||
// Any pending writes are written out to storage as though
|
|
||||||
// sync had been called and releases any allocated resources.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
|
|
||||||
|
|
||||||
// Synchronize a file on storage
|
|
||||||
//
|
|
||||||
// Any pending writes are written out to storage.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
|
|
||||||
|
|
||||||
// Read data from file
|
|
||||||
//
|
|
||||||
// Takes a buffer and size indicating where to store the read data.
|
|
||||||
// Returns the number of bytes read, or a negative error code on failure.
|
|
||||||
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Write data to file
|
|
||||||
//
|
|
||||||
// Takes a buffer and size indicating the data to write. The file will not
|
|
||||||
// actually be updated on the storage until either sync or close is called.
|
|
||||||
//
|
|
||||||
// Returns the number of bytes written, or a negative error code on failure.
|
|
||||||
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
const void *buffer, lfs_size_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Change the position of the file
|
|
||||||
//
|
|
||||||
// The change in position is determined by the offset and whence flag.
|
|
||||||
// Returns the new position of the file, or a negative error code on failure.
|
|
||||||
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
|
|
||||||
lfs_soff_t off, int whence);
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Truncates the size of the file to the specified size
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Return the position of the file
|
|
||||||
//
|
|
||||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
|
||||||
// Returns the position of the file, or a negative error code on failure.
|
|
||||||
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
|
|
||||||
|
|
||||||
// Change the position of the file to the beginning of the file
|
|
||||||
//
|
|
||||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
|
|
||||||
|
|
||||||
// Return the size of the file
|
|
||||||
//
|
|
||||||
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
|
|
||||||
// Returns the size of the file, or a negative error code on failure.
|
|
||||||
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
|
||||||
|
|
||||||
|
|
||||||
/// Directory operations ///
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
// Create a directory
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_mkdir(lfs_t *lfs, const char *path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Open a directory
|
|
||||||
//
|
|
||||||
// Once open a directory can be used with read to iterate over files.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
|
|
||||||
|
|
||||||
// Close a directory
|
|
||||||
//
|
|
||||||
// Releases any allocated resources.
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
|
|
||||||
|
|
||||||
// Read an entry in the directory
|
|
||||||
//
|
|
||||||
// Fills out the info structure, based on the specified file or directory.
|
|
||||||
// Returns a positive value on success, 0 at the end of directory,
|
|
||||||
// or a negative error code on failure.
|
|
||||||
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
|
||||||
|
|
||||||
// Change the position of the directory
|
|
||||||
//
|
|
||||||
// The new off must be a value previous returned from tell and specifies
|
|
||||||
// an absolute offset in the directory seek.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
|
|
||||||
|
|
||||||
// Return the position of the directory
|
|
||||||
//
|
|
||||||
// The returned offset is only meant to be consumed by seek and may not make
|
|
||||||
// sense, but does indicate the current position in the directory iteration.
|
|
||||||
//
|
|
||||||
// Returns the position of the directory, or a negative error code on failure.
|
|
||||||
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
|
|
||||||
|
|
||||||
// Change the position of the directory to the beginning of the directory
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
|
||||||
|
|
||||||
|
|
||||||
/// Filesystem-level filesystem operations
|
|
||||||
|
|
||||||
// Finds the current size of the filesystem
|
|
||||||
//
|
|
||||||
// Note: Result is best effort. If files share COW structures, the returned
|
|
||||||
// size may be larger than the filesystem actually is.
|
|
||||||
//
|
|
||||||
// Returns the number of allocated blocks, or a negative error code on failure.
|
|
||||||
lfs_ssize_t lfs_fs_size(lfs_t *lfs);
|
|
||||||
|
|
||||||
// Traverse through all blocks in use by the filesystem
|
|
||||||
//
|
|
||||||
// The provided callback will be called with each block address that is
|
|
||||||
// currently in use by the filesystem. This can be used to determine which
|
|
||||||
// blocks are in use or how much of the storage is available.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
|
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
|
||||||
#ifdef LFS_MIGRATE
|
|
||||||
// Attempts to migrate a previous version of littlefs
|
|
||||||
//
|
|
||||||
// Behaves similarly to the lfs_format function. Attempts to mount
|
|
||||||
// the previous version of littlefs and update the filesystem so it can be
|
|
||||||
// mounted with the current version of littlefs.
|
|
||||||
//
|
|
||||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
|
||||||
// object, and does not leave the filesystem mounted. The config struct must
|
|
||||||
// be zeroed for defaults and backwards compatibility.
|
|
||||||
//
|
|
||||||
// Returns a negative error code on failure.
|
|
||||||
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* lfs util functions
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
#include "lfs_util.h"
|
|
||||||
|
|
||||||
// Only compile if user does not provide custom config
|
|
||||||
#ifndef LFS_CONFIG
|
|
||||||
|
|
||||||
|
|
||||||
// Software CRC implementation with small lookup table
|
|
||||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
|
||||||
static const uint32_t rtable[16] = {
|
|
||||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
|
||||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
|
||||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
|
||||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t *data = buffer;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
|
|
||||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
|
|
||||||
}
|
|
||||||
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
/*
|
|
||||||
* lfs utility functions
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*/
|
|
||||||
#ifndef LFS_UTIL_H
|
|
||||||
#define LFS_UTIL_H
|
|
||||||
|
|
||||||
// Users can override lfs_util.h with their own configuration by defining
|
|
||||||
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
|
||||||
//
|
|
||||||
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
|
||||||
// provided by the config file. To start, I would suggest copying lfs_util.h
|
|
||||||
// and modifying as needed.
|
|
||||||
#ifdef LFS_CONFIG
|
|
||||||
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
|
||||||
#define LFS_STRINGIZE2(x) #x
|
|
||||||
#include LFS_STRINGIZE(LFS_CONFIG)
|
|
||||||
#else
|
|
||||||
|
|
||||||
// System includes
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifndef LFS_NO_MALLOC
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#ifndef LFS_NO_ASSERT
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(LFS_NO_DEBUG) || \
|
|
||||||
!defined(LFS_NO_WARN) || \
|
|
||||||
!defined(LFS_NO_ERROR) || \
|
|
||||||
defined(LFS_YES_TRACE)
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Macros, may be replaced by system specific wrappers. Arguments to these
|
|
||||||
// macros must not have side-effects as the macros can be removed for a smaller
|
|
||||||
// code footprint
|
|
||||||
|
|
||||||
// Logging functions
|
|
||||||
#ifndef LFS_TRACE
|
|
||||||
#ifdef LFS_YES_TRACE
|
|
||||||
#define LFS_TRACE_(fmt, ...) \
|
|
||||||
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
|
||||||
#else
|
|
||||||
#define LFS_TRACE(...)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LFS_DEBUG
|
|
||||||
#ifndef LFS_NO_DEBUG
|
|
||||||
#define LFS_DEBUG_(fmt, ...) \
|
|
||||||
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
|
|
||||||
#else
|
|
||||||
#define LFS_DEBUG(...)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LFS_WARN
|
|
||||||
#ifndef LFS_NO_WARN
|
|
||||||
#define LFS_WARN_(fmt, ...) \
|
|
||||||
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
|
|
||||||
#else
|
|
||||||
#define LFS_WARN(...)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LFS_ERROR
|
|
||||||
#ifndef LFS_NO_ERROR
|
|
||||||
#define LFS_ERROR_(fmt, ...) \
|
|
||||||
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
|
||||||
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
|
|
||||||
#else
|
|
||||||
#define LFS_ERROR(...)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Runtime assertions
|
|
||||||
#ifndef LFS_ASSERT
|
|
||||||
#ifndef LFS_NO_ASSERT
|
|
||||||
#define LFS_ASSERT(test) assert(test)
|
|
||||||
#else
|
|
||||||
#define LFS_ASSERT(test)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Builtin functions, these may be replaced by more efficient
|
|
||||||
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
|
||||||
// expensive basic C implementation for debugging purposes
|
|
||||||
|
|
||||||
// Min/max functions for unsigned 32-bit numbers
|
|
||||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
|
||||||
return (a > b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
|
|
||||||
return (a < b) ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align to nearest multiple of a size
|
|
||||||
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
|
|
||||||
return a - (a % alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
|
|
||||||
return lfs_aligndown(a + alignment-1, alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the smallest power of 2 greater than or equal to a
|
|
||||||
static inline uint32_t lfs_npw2(uint32_t a) {
|
|
||||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
|
||||||
return 32 - __builtin_clz(a-1);
|
|
||||||
#else
|
|
||||||
uint32_t r = 0;
|
|
||||||
uint32_t s;
|
|
||||||
a -= 1;
|
|
||||||
s = (a > 0xffff) << 4; a >>= s; r |= s;
|
|
||||||
s = (a > 0xff ) << 3; a >>= s; r |= s;
|
|
||||||
s = (a > 0xf ) << 2; a >>= s; r |= s;
|
|
||||||
s = (a > 0x3 ) << 1; a >>= s; r |= s;
|
|
||||||
return (r | (a >> 1)) + 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count the number of trailing binary zeros in a
|
|
||||||
// lfs_ctz(0) may be undefined
|
|
||||||
static inline uint32_t lfs_ctz(uint32_t a) {
|
|
||||||
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
|
||||||
return __builtin_ctz(a);
|
|
||||||
#else
|
|
||||||
return lfs_npw2((a & -a) + 1) - 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count the number of binary ones in a
|
|
||||||
static inline uint32_t lfs_popc(uint32_t a) {
|
|
||||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
|
||||||
return __builtin_popcount(a);
|
|
||||||
#else
|
|
||||||
a = a - ((a >> 1) & 0x55555555);
|
|
||||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
|
||||||
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the sequence comparison of a and b, this is the distance
|
|
||||||
// between a and b ignoring overflow
|
|
||||||
static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
|
||||||
return (int)(unsigned)(a - b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert between 32-bit little-endian and native order
|
|
||||||
static inline uint32_t lfs_fromle32(uint32_t a) {
|
|
||||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
|
||||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
|
||||||
return a;
|
|
||||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
|
||||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
|
||||||
return __builtin_bswap32(a);
|
|
||||||
#else
|
|
||||||
return (((uint8_t*)&a)[0] << 0) |
|
|
||||||
(((uint8_t*)&a)[1] << 8) |
|
|
||||||
(((uint8_t*)&a)[2] << 16) |
|
|
||||||
(((uint8_t*)&a)[3] << 24);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t lfs_tole32(uint32_t a) {
|
|
||||||
return lfs_fromle32(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert between 32-bit big-endian and native order
|
|
||||||
static inline uint32_t lfs_frombe32(uint32_t a) {
|
|
||||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
|
||||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
|
||||||
return __builtin_bswap32(a);
|
|
||||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
|
||||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
|
||||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
|
||||||
return a;
|
|
||||||
#else
|
|
||||||
return (((uint8_t*)&a)[0] << 24) |
|
|
||||||
(((uint8_t*)&a)[1] << 16) |
|
|
||||||
(((uint8_t*)&a)[2] << 8) |
|
|
||||||
(((uint8_t*)&a)[3] << 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t lfs_tobe32(uint32_t a) {
|
|
||||||
return lfs_frombe32(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate CRC-32 with polynomial = 0x04c11db7
|
|
||||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
|
|
||||||
|
|
||||||
// Allocate memory, only used if buffers are not provided to littlefs
|
|
||||||
// Note, memory must be 64-bit aligned
|
|
||||||
static inline void *lfs_malloc(size_t size) {
|
|
||||||
#ifndef LFS_NO_MALLOC
|
|
||||||
return malloc(size);
|
|
||||||
#else
|
|
||||||
(void)size;
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
|
||||||
static inline void lfs_free(void *p) {
|
|
||||||
#ifndef LFS_NO_MALLOC
|
|
||||||
free(p);
|
|
||||||
#else
|
|
||||||
(void)p;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file littlefs_api.c
|
|
||||||
* @brief Maps the HAL of esp_partition <-> littlefs
|
|
||||||
* @author Brian Pugh
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ESP_LOCAL_LOG_LEVEL ESP_LOG_INFO
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_partition.h"
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "lfs.h"
|
|
||||||
#include "esp_littlefs.h"
|
|
||||||
#include "littlefs_api.h"
|
|
||||||
|
|
||||||
static const char TAG[] = "esp_littlefs_api";
|
|
||||||
|
|
||||||
int littlefs_api_read(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, void *buffer, lfs_size_t size) {
|
|
||||||
esp_littlefs_t * efs = c->context;
|
|
||||||
size_t part_off = (block * c->block_size) + off;
|
|
||||||
esp_err_t err = esp_partition_read(efs->partition, part_off, buffer, size);
|
|
||||||
if (err) {
|
|
||||||
ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", part_off, size, err);
|
|
||||||
return LFS_ERR_IO;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, const void *buffer, lfs_size_t size) {
|
|
||||||
esp_littlefs_t * efs = c->context;
|
|
||||||
size_t part_off = (block * c->block_size) + off;
|
|
||||||
esp_err_t err = esp_partition_write(efs->partition, part_off, buffer, size);
|
|
||||||
if (err) {
|
|
||||||
ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", part_off, size, err);
|
|
||||||
return LFS_ERR_IO;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block) {
|
|
||||||
esp_littlefs_t * efs = c->context;
|
|
||||||
size_t part_off = block * c->block_size;
|
|
||||||
esp_err_t err = esp_partition_erase_range(efs->partition, part_off, c->block_size);
|
|
||||||
if (err) {
|
|
||||||
ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", part_off, c->block_size, err);
|
|
||||||
return LFS_ERR_IO;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int littlefs_api_sync(const struct lfs_config *c) {
|
|
||||||
/* Unnecessary for esp-idf */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
#ifndef ESP_LITTLEFS_API_H__
|
|
||||||
#define ESP_LITTLEFS_API_H__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "esp_partition.h"
|
|
||||||
#include "lfs.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief a file descriptor
|
|
||||||
* That's also a singly linked list used for keeping tracks of all opened file descriptor
|
|
||||||
*
|
|
||||||
* Shortcomings/potential issues of 32-bit hash (when CONFIG_LITTLEFS_USE_ONLY_HASH) listed here:
|
|
||||||
* * unlink - If a different file is open that generates a hash collision, it will report an
|
|
||||||
* error that it cannot unlink an open file.
|
|
||||||
* * rename - If a different file is open that generates a hash collision with
|
|
||||||
* src or dst, it will report an error that it cannot rename an open file.
|
|
||||||
* Potential consequences:
|
|
||||||
* 1. A file cannot be deleted while a collision-geneating file is open.
|
|
||||||
* Worst-case, if the other file is always open during the lifecycle
|
|
||||||
* of your app, it's collision file cannot be deleted, which in the
|
|
||||||
* worst-case could cause storage-capacity issues.
|
|
||||||
* 2. Same as (1), but for renames
|
|
||||||
*/
|
|
||||||
typedef struct _vfs_littlefs_file_t {
|
|
||||||
lfs_file_t file;
|
|
||||||
uint32_t hash;
|
|
||||||
struct _vfs_littlefs_file_t * next; /*!< Pointer to next file in Singly Linked List */
|
|
||||||
#ifndef CONFIG_LITTLEFS_USE_ONLY_HASH
|
|
||||||
char * path;
|
|
||||||
#endif
|
|
||||||
} vfs_littlefs_file_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief littlefs definition structure
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
lfs_t *fs; /*!< Handle to the underlying littlefs */
|
|
||||||
SemaphoreHandle_t lock; /*!< FS lock */
|
|
||||||
const esp_partition_t* partition; /*!< The partition on which littlefs is located */
|
|
||||||
char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */
|
|
||||||
|
|
||||||
struct lfs_config cfg; /*!< littlefs Mount configuration */
|
|
||||||
|
|
||||||
vfs_littlefs_file_t *file; /*!< Singly Linked List of files */
|
|
||||||
|
|
||||||
vfs_littlefs_file_t **cache; /*!< A cache of pointers to the opened files */
|
|
||||||
uint16_t cache_size; /*!< The cache allocated size (in pointers) */
|
|
||||||
uint16_t fd_count; /*!< The count of opened file descriptor used to speed up computation */
|
|
||||||
} esp_littlefs_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a region in a block.
|
|
||||||
*
|
|
||||||
* Negative error codes are propogated to the user.
|
|
||||||
*
|
|
||||||
* @return errorcode. 0 on success.
|
|
||||||
*/
|
|
||||||
int littlefs_api_read(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Program a region in a block.
|
|
||||||
*
|
|
||||||
* The block must have previously been erased.
|
|
||||||
* Negative error codes are propogated to the user.
|
|
||||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
||||||
*
|
|
||||||
* @return errorcode. 0 on success.
|
|
||||||
*/
|
|
||||||
int littlefs_api_prog(const struct lfs_config *c, lfs_block_t block,
|
|
||||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Erase a block.
|
|
||||||
*
|
|
||||||
* A block must be erased before being programmed.
|
|
||||||
* The state of an erased block is undefined.
|
|
||||||
* Negative error codes are propogated to the user.
|
|
||||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
|
||||||
* @return errorcode. 0 on success.
|
|
||||||
*/
|
|
||||||
int littlefs_api_erase(const struct lfs_config *c, lfs_block_t block);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sync the state of the underlying block device.
|
|
||||||
*
|
|
||||||
* Negative error codes are propogated to the user.
|
|
||||||
*
|
|
||||||
* @return errorcode. 0 on success.
|
|
||||||
*/
|
|
||||||
int littlefs_api_sync(const struct lfs_config *c);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -141,114 +141,104 @@ sample code bearing this copyright.
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "OneWire.h"
|
#include "OneWire.h"
|
||||||
#include "OneWire_direct_gpio.h"
|
#include "util/OneWire_direct_gpio.h"
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
||||||
|
|
||||||
void OneWire::begin(uint8_t pin) {
|
void OneWire::begin(uint8_t pin)
|
||||||
pinMode(pin, INPUT);
|
{
|
||||||
bitmask = PIN_TO_BITMASK(pin);
|
pinMode(pin, INPUT);
|
||||||
baseReg = PIN_TO_BASEREG(pin);
|
bitmask = PIN_TO_BITMASK(pin);
|
||||||
|
baseReg = PIN_TO_BASEREG(pin);
|
||||||
#if ONEWIRE_SEARCH
|
#if ONEWIRE_SEARCH
|
||||||
reset_search();
|
reset_search();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Perform the onewire reset function. We will wait up to 250uS for
|
// Perform the onewire reset function. We will wait up to 250uS for
|
||||||
// the bus to come high, if it doesn't then it is broken or shorted
|
// the bus to come high, if it doesn't then it is broken or shorted
|
||||||
// and we return a 0;
|
// and we return a 0;
|
||||||
//
|
//
|
||||||
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
|
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
|
||||||
//
|
//
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
uint8_t OneWire::reset(void)
|
||||||
uint8_t IRAM_ATTR OneWire::reset(void) {
|
{
|
||||||
#else
|
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
||||||
uint8_t OneWire::reset(void) {
|
volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
|
||||||
#endif
|
uint8_t r;
|
||||||
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
uint8_t retries = 125;
|
||||||
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg;
|
|
||||||
uint8_t r;
|
|
||||||
uint8_t retries = 125;
|
|
||||||
|
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_MODE_INPUT(reg, mask);
|
DIRECT_MODE_INPUT(reg, mask);
|
||||||
interrupts();
|
interrupts();
|
||||||
// wait until the wire is high... just in case
|
// wait until the wire is high... just in case
|
||||||
do {
|
do {
|
||||||
if (--retries == 0)
|
if (--retries == 0) return 0;
|
||||||
return 0;
|
delayMicroseconds(2);
|
||||||
delayMicroseconds(2);
|
} while ( !DIRECT_READ(reg, mask));
|
||||||
} while (!DIRECT_READ(reg, mask));
|
|
||||||
|
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_WRITE_LOW(reg, mask);
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
interrupts();
|
interrupts();
|
||||||
delayMicroseconds(480);
|
delayMicroseconds(480);
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_MODE_INPUT(reg, mask); // allow it to float
|
DIRECT_MODE_INPUT(reg, mask); // allow it to float
|
||||||
delayMicroseconds(70);
|
delayMicroseconds(70);
|
||||||
r = !DIRECT_READ(reg, mask);
|
r = !DIRECT_READ(reg, mask);
|
||||||
interrupts();
|
interrupts();
|
||||||
delayMicroseconds(410);
|
delayMicroseconds(410);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Write a bit. Port and bit is used to cut lookup time and provide
|
// Write a bit. Port and bit is used to cut lookup time and provide
|
||||||
// more certain timing.
|
// more certain timing.
|
||||||
//
|
//
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
void OneWire::write_bit(uint8_t v)
|
||||||
void IRAM_ATTR OneWire::write_bit(uint8_t v) {
|
{
|
||||||
#else
|
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
||||||
void OneWire::write_bit(uint8_t v) {
|
volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
|
||||||
#endif
|
|
||||||
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
|
||||||
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg;
|
|
||||||
|
|
||||||
if (v & 1) {
|
if (v & 1) {
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_WRITE_LOW(reg, mask);
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
delayMicroseconds(10);
|
delayMicroseconds(10);
|
||||||
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
||||||
interrupts();
|
interrupts();
|
||||||
delayMicroseconds(55);
|
delayMicroseconds(55);
|
||||||
} else {
|
} else {
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_WRITE_LOW(reg, mask);
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
|
||||||
delayMicroseconds(65);
|
delayMicroseconds(65);
|
||||||
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
DIRECT_WRITE_HIGH(reg, mask); // drive output high
|
||||||
interrupts();
|
interrupts();
|
||||||
delayMicroseconds(5);
|
delayMicroseconds(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read a bit. Port and bit is used to cut lookup time and provide
|
// Read a bit. Port and bit is used to cut lookup time and provide
|
||||||
// more certain timing.
|
// more certain timing.
|
||||||
//
|
//
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
uint8_t OneWire::read_bit(void)
|
||||||
uint8_t IRAM_ATTR OneWire::read_bit(void) {
|
{
|
||||||
#else
|
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
||||||
uint8_t OneWire::read_bit(void) {
|
volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg;
|
||||||
#endif
|
uint8_t r;
|
||||||
IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask;
|
|
||||||
volatile IO_REG_TYPE * reg IO_REG_BASE_ATTR = baseReg;
|
|
||||||
uint8_t r;
|
|
||||||
|
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_MODE_OUTPUT(reg, mask);
|
DIRECT_MODE_OUTPUT(reg, mask);
|
||||||
DIRECT_WRITE_LOW(reg, mask);
|
DIRECT_WRITE_LOW(reg, mask);
|
||||||
delayMicroseconds(3);
|
delayMicroseconds(3);
|
||||||
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
|
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
|
||||||
delayMicroseconds(10);
|
delayMicroseconds(10);
|
||||||
r = DIRECT_READ(reg, mask);
|
r = DIRECT_READ(reg, mask);
|
||||||
interrupts();
|
interrupts();
|
||||||
delayMicroseconds(53);
|
delayMicroseconds(53);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -262,25 +252,25 @@ void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
|
|||||||
uint8_t bitMask;
|
uint8_t bitMask;
|
||||||
|
|
||||||
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||||
OneWire::write_bit((bitMask & v) ? 1 : 0);
|
OneWire::write_bit( (bitMask & v)?1:0);
|
||||||
}
|
}
|
||||||
if (!power) {
|
if ( !power) {
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_MODE_INPUT(baseReg, bitmask);
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
DIRECT_WRITE_LOW(baseReg, bitmask);
|
DIRECT_WRITE_LOW(baseReg, bitmask);
|
||||||
interrupts();
|
interrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneWire::write_bytes(const uint8_t * buf, uint16_t count, bool power /* = 0 */) {
|
void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
|
||||||
for (uint16_t i = 0; i < count; i++)
|
for (uint16_t i = 0 ; i < count ; i++)
|
||||||
write(buf[i]);
|
write(buf[i]);
|
||||||
if (!power) {
|
if (!power) {
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
DIRECT_MODE_INPUT(baseReg, bitmask);
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
DIRECT_WRITE_LOW(baseReg, bitmask);
|
DIRECT_WRITE_LOW(baseReg, bitmask);
|
||||||
interrupts();
|
interrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -291,40 +281,41 @@ uint8_t OneWire::read() {
|
|||||||
uint8_t r = 0;
|
uint8_t r = 0;
|
||||||
|
|
||||||
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
for (bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||||
if (OneWire::read_bit())
|
if ( OneWire::read_bit()) r |= bitMask;
|
||||||
r |= bitMask;
|
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneWire::read_bytes(uint8_t * buf, uint16_t count) {
|
void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
|
||||||
for (uint16_t i = 0; i < count; i++)
|
for (uint16_t i = 0 ; i < count ; i++)
|
||||||
buf[i] = read();
|
buf[i] = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do a ROM select
|
// Do a ROM select
|
||||||
//
|
//
|
||||||
void OneWire::select(const uint8_t rom[8]) {
|
void OneWire::select(const uint8_t rom[8])
|
||||||
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
||||||
write(0x55); // Choose ROM
|
write(0x55); // Choose ROM
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++) write(rom[i]);
|
||||||
write(rom[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do a ROM skip
|
// Do a ROM skip
|
||||||
//
|
//
|
||||||
void OneWire::skip() {
|
void OneWire::skip()
|
||||||
write(0xCC); // Skip ROM
|
{
|
||||||
|
write(0xCC); // Skip ROM
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneWire::depower() {
|
void OneWire::depower()
|
||||||
noInterrupts();
|
{
|
||||||
DIRECT_MODE_INPUT(baseReg, bitmask);
|
noInterrupts();
|
||||||
interrupts();
|
DIRECT_MODE_INPUT(baseReg, bitmask);
|
||||||
|
interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ONEWIRE_SEARCH
|
#if ONEWIRE_SEARCH
|
||||||
@@ -333,29 +324,30 @@ void OneWire::depower() {
|
|||||||
// You need to use this function to start a search again from the beginning.
|
// You need to use this function to start a search again from the beginning.
|
||||||
// You do not need to do it for the first search, though you could.
|
// You do not need to do it for the first search, though you could.
|
||||||
//
|
//
|
||||||
void OneWire::reset_search() {
|
void OneWire::reset_search()
|
||||||
// reset the search state
|
{
|
||||||
LastDiscrepancy = 0;
|
// reset the search state
|
||||||
LastDeviceFlag = false;
|
LastDiscrepancy = 0;
|
||||||
LastFamilyDiscrepancy = 0;
|
LastDeviceFlag = false;
|
||||||
for (int i = 7;; i--) {
|
LastFamilyDiscrepancy = 0;
|
||||||
ROM_NO[i] = 0;
|
for(int i = 7; ; i--) {
|
||||||
if (i == 0)
|
ROM_NO[i] = 0;
|
||||||
break;
|
if ( i == 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the search to find the device type 'family_code' on the next call
|
// Setup the search to find the device type 'family_code' on the next call
|
||||||
// to search(*newAddr) if it is present.
|
// to search(*newAddr) if it is present.
|
||||||
//
|
//
|
||||||
void OneWire::target_search(uint8_t family_code) {
|
void OneWire::target_search(uint8_t family_code)
|
||||||
// set the search state to find SearchFamily type devices
|
{
|
||||||
ROM_NO[0] = family_code;
|
// set the search state to find SearchFamily type devices
|
||||||
for (uint8_t i = 1; i < 8; i++)
|
ROM_NO[0] = family_code;
|
||||||
ROM_NO[i] = 0;
|
for (uint8_t i = 1; i < 8; i++)
|
||||||
LastDiscrepancy = 64;
|
ROM_NO[i] = 0;
|
||||||
LastFamilyDiscrepancy = 0;
|
LastDiscrepancy = 64;
|
||||||
LastDeviceFlag = false;
|
LastFamilyDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -374,120 +366,121 @@ void OneWire::target_search(uint8_t family_code) {
|
|||||||
// Return TRUE : device found, ROM number in ROM_NO buffer
|
// Return TRUE : device found, ROM number in ROM_NO buffer
|
||||||
// FALSE : device not found, end of search
|
// FALSE : device not found, end of search
|
||||||
//
|
//
|
||||||
bool OneWire::search(uint8_t * newAddr, bool search_mode /* = true */) {
|
bool OneWire::search(uint8_t *newAddr, bool search_mode /* = true */)
|
||||||
uint8_t id_bit_number;
|
{
|
||||||
uint8_t last_zero, rom_byte_number;
|
uint8_t id_bit_number;
|
||||||
bool search_result;
|
uint8_t last_zero, rom_byte_number;
|
||||||
uint8_t id_bit, cmp_id_bit;
|
bool search_result;
|
||||||
|
uint8_t id_bit, cmp_id_bit;
|
||||||
|
|
||||||
unsigned char rom_byte_mask, search_direction;
|
unsigned char rom_byte_mask, search_direction;
|
||||||
|
|
||||||
// initialize for search
|
// initialize for search
|
||||||
id_bit_number = 1;
|
id_bit_number = 1;
|
||||||
last_zero = 0;
|
last_zero = 0;
|
||||||
rom_byte_number = 0;
|
rom_byte_number = 0;
|
||||||
rom_byte_mask = 1;
|
rom_byte_mask = 1;
|
||||||
search_result = false;
|
search_result = false;
|
||||||
|
|
||||||
// if the last call was not the last one
|
// if the last call was not the last one
|
||||||
if (!LastDeviceFlag) {
|
if (!LastDeviceFlag) {
|
||||||
// 1-Wire reset
|
// 1-Wire reset
|
||||||
if (!reset()) {
|
if (!reset()) {
|
||||||
// reset the search
|
// reset the search
|
||||||
LastDiscrepancy = 0;
|
LastDiscrepancy = 0;
|
||||||
LastDeviceFlag = false;
|
LastDeviceFlag = false;
|
||||||
LastFamilyDiscrepancy = 0;
|
LastFamilyDiscrepancy = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// issue the search command
|
// issue the search command
|
||||||
if (search_mode == true) {
|
if (search_mode == true) {
|
||||||
write(0xF0); // NORMAL SEARCH
|
write(0xF0); // NORMAL SEARCH
|
||||||
} else {
|
} else {
|
||||||
write(0xEC); // CONDITIONAL SEARCH
|
write(0xEC); // CONDITIONAL SEARCH
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop to do the search
|
// loop to do the search
|
||||||
do {
|
do
|
||||||
// read a bit and its complement
|
{
|
||||||
id_bit = read_bit();
|
// read a bit and its complement
|
||||||
cmp_id_bit = read_bit();
|
id_bit = read_bit();
|
||||||
|
cmp_id_bit = read_bit();
|
||||||
|
|
||||||
// check for no devices on 1-wire
|
// check for no devices on 1-wire
|
||||||
if ((id_bit == 1) && (cmp_id_bit == 1)) {
|
if ((id_bit == 1) && (cmp_id_bit == 1)) {
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
// all devices coupled have 0 or 1
|
||||||
|
if (id_bit != cmp_id_bit) {
|
||||||
|
search_direction = id_bit; // bit write value for search
|
||||||
} else {
|
} else {
|
||||||
// all devices coupled have 0 or 1
|
// if this discrepancy if before the Last Discrepancy
|
||||||
if (id_bit != cmp_id_bit) {
|
// on a previous next then pick the same as last time
|
||||||
search_direction = id_bit; // bit write value for search
|
if (id_bit_number < LastDiscrepancy) {
|
||||||
} else {
|
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
|
||||||
// if this discrepancy if before the Last Discrepancy
|
} else {
|
||||||
// on a previous next then pick the same as last time
|
// if equal to last pick 1, if not then pick 0
|
||||||
if (id_bit_number < LastDiscrepancy) {
|
search_direction = (id_bit_number == LastDiscrepancy);
|
||||||
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
|
}
|
||||||
} else {
|
// if 0 was picked then record its position in LastZero
|
||||||
// if equal to last pick 1, if not then pick 0
|
if (search_direction == 0) {
|
||||||
search_direction = (id_bit_number == LastDiscrepancy);
|
last_zero = id_bit_number;
|
||||||
}
|
|
||||||
// if 0 was picked then record its position in LastZero
|
|
||||||
if (search_direction == 0) {
|
|
||||||
last_zero = id_bit_number;
|
|
||||||
|
|
||||||
// check for Last discrepancy in family
|
// check for Last discrepancy in family
|
||||||
if (last_zero < 9)
|
if (last_zero < 9)
|
||||||
LastFamilyDiscrepancy = last_zero;
|
LastFamilyDiscrepancy = last_zero;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// set or clear the bit in the ROM byte rom_byte_number
|
|
||||||
// with mask rom_byte_mask
|
|
||||||
if (search_direction == 1)
|
|
||||||
ROM_NO[rom_byte_number] |= rom_byte_mask;
|
|
||||||
else
|
|
||||||
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
|
|
||||||
|
|
||||||
// serial number search direction write bit
|
|
||||||
write_bit(search_direction);
|
|
||||||
|
|
||||||
// increment the byte counter id_bit_number
|
|
||||||
// and shift the mask rom_byte_mask
|
|
||||||
id_bit_number++;
|
|
||||||
rom_byte_mask <<= 1;
|
|
||||||
|
|
||||||
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
|
|
||||||
if (rom_byte_mask == 0) {
|
|
||||||
rom_byte_number++;
|
|
||||||
rom_byte_mask = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
|
|
||||||
|
|
||||||
// if the search was successful then
|
// set or clear the bit in the ROM byte rom_byte_number
|
||||||
if (!(id_bit_number < 65)) {
|
// with mask rom_byte_mask
|
||||||
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
|
if (search_direction == 1)
|
||||||
LastDiscrepancy = last_zero;
|
ROM_NO[rom_byte_number] |= rom_byte_mask;
|
||||||
|
else
|
||||||
|
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
|
||||||
|
|
||||||
// check for last device
|
// serial number search direction write bit
|
||||||
if (LastDiscrepancy == 0) {
|
write_bit(search_direction);
|
||||||
LastDeviceFlag = true;
|
|
||||||
|
// increment the byte counter id_bit_number
|
||||||
|
// and shift the mask rom_byte_mask
|
||||||
|
id_bit_number++;
|
||||||
|
rom_byte_mask <<= 1;
|
||||||
|
|
||||||
|
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
|
||||||
|
if (rom_byte_mask == 0) {
|
||||||
|
rom_byte_number++;
|
||||||
|
rom_byte_mask = 1;
|
||||||
}
|
}
|
||||||
search_result = true;
|
}
|
||||||
}
|
}
|
||||||
}
|
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
|
||||||
|
|
||||||
// if no device found then reset counters so next 'search' will be like a first
|
// if the search was successful then
|
||||||
if (!search_result || !ROM_NO[0]) {
|
if (!(id_bit_number < 65)) {
|
||||||
LastDiscrepancy = 0;
|
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
|
||||||
LastDeviceFlag = false;
|
LastDiscrepancy = last_zero;
|
||||||
LastFamilyDiscrepancy = 0;
|
|
||||||
search_result = false;
|
// check for last device
|
||||||
} else {
|
if (LastDiscrepancy == 0) {
|
||||||
for (int i = 0; i < 8; i++)
|
LastDeviceFlag = true;
|
||||||
newAddr[i] = ROM_NO[i];
|
}
|
||||||
}
|
search_result = true;
|
||||||
// depower(); // https://github.com/PaulStoffregen/OneWire/pull/80
|
}
|
||||||
return search_result;
|
}
|
||||||
}
|
|
||||||
|
// if no device found then reset counters so next 'search' will be like a first
|
||||||
|
if (!search_result || !ROM_NO[0]) {
|
||||||
|
LastDiscrepancy = 0;
|
||||||
|
LastDeviceFlag = false;
|
||||||
|
LastFamilyDiscrepancy = 0;
|
||||||
|
search_result = false;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
|
||||||
|
}
|
||||||
|
return search_result;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -500,82 +493,88 @@ bool OneWire::search(uint8_t * newAddr, bool search_mode /* = true */) {
|
|||||||
// Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
|
// Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
|
||||||
// Tiny 2x16 entry CRC table created by Arjen Lentz
|
// Tiny 2x16 entry CRC table created by Arjen Lentz
|
||||||
// See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
|
// See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
|
||||||
static const uint8_t PROGMEM dscrc2x16_table[] = {0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
|
static const uint8_t PROGMEM dscrc2x16_table[] = {
|
||||||
0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8, 0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74};
|
0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
|
||||||
|
0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
|
||||||
|
0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
|
||||||
|
0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74
|
||||||
|
};
|
||||||
|
|
||||||
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
|
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
|
||||||
// and the registers. (Use tiny 2x16 entry CRC table)
|
// and the registers. (Use tiny 2x16 entry CRC table)
|
||||||
uint8_t OneWire::crc8(const uint8_t * addr, uint8_t len) {
|
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
|
||||||
uint8_t crc = 0;
|
{
|
||||||
|
uint8_t crc = 0;
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
crc = *addr++ ^ crc; // just re-using crc as intermediate
|
crc = *addr++ ^ crc; // just re-using crc as intermediate
|
||||||
crc = pgm_read_byte(dscrc2x16_table + (crc & 0x0f)) ^ pgm_read_byte(dscrc2x16_table + 16 + ((crc >> 4) & 0x0f));
|
crc = pgm_read_byte(dscrc2x16_table + (crc & 0x0f)) ^
|
||||||
}
|
pgm_read_byte(dscrc2x16_table + 16 + ((crc >> 4) & 0x0f));
|
||||||
|
}
|
||||||
|
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//
|
//
|
||||||
// Compute a Dallas Semiconductor 8 bit CRC directly.
|
// Compute a Dallas Semiconductor 8 bit CRC directly.
|
||||||
// this is much slower, but a little smaller, than the lookup table.
|
// this is much slower, but a little smaller, than the lookup table.
|
||||||
//
|
//
|
||||||
uint8_t OneWire::crc8(const uint8_t * addr, uint8_t len) {
|
uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
|
||||||
uint8_t crc = 0;
|
{
|
||||||
|
uint8_t crc = 0;
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
#if defined(__AVR__)
|
#if defined(__AVR__)
|
||||||
crc = _crc_ibutton_update(crc, *addr++);
|
crc = _crc_ibutton_update(crc, *addr++);
|
||||||
#else
|
#else
|
||||||
uint8_t inbyte = *addr++;
|
uint8_t inbyte = *addr++;
|
||||||
for (uint8_t i = 8; i; i--) {
|
for (uint8_t i = 8; i; i--) {
|
||||||
uint8_t mix = (crc ^ inbyte) & 0x01;
|
uint8_t mix = (crc ^ inbyte) & 0x01;
|
||||||
crc >>= 1;
|
crc >>= 1;
|
||||||
if (mix)
|
if (mix) crc ^= 0x8C;
|
||||||
crc ^= 0x8C;
|
inbyte >>= 1;
|
||||||
inbyte >>= 1;
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ONEWIRE_CRC16
|
#if ONEWIRE_CRC16
|
||||||
bool OneWire::check_crc16(const uint8_t * input, uint16_t len, const uint8_t * inverted_crc, uint16_t crc) {
|
bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc)
|
||||||
|
{
|
||||||
crc = ~crc16(input, len, crc);
|
crc = ~crc16(input, len, crc);
|
||||||
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
|
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t OneWire::crc16(const uint8_t * input, uint16_t len, uint16_t crc) {
|
uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc)
|
||||||
|
{
|
||||||
#if defined(__AVR__)
|
#if defined(__AVR__)
|
||||||
for (uint16_t i = 0; i < len; i++) {
|
for (uint16_t i = 0 ; i < len ; i++) {
|
||||||
crc = _crc16_update(crc, input[i]);
|
crc = _crc16_update(crc, input[i]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static const uint8_t oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
|
static const uint8_t oddparity[16] =
|
||||||
|
{ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
|
||||||
|
|
||||||
for (uint16_t i = 0; i < len; i++) {
|
for (uint16_t i = 0 ; i < len ; i++) {
|
||||||
// Even though we're just copying a byte from the input,
|
// Even though we're just copying a byte from the input,
|
||||||
// we'll be doing 16-bit computation with it.
|
// we'll be doing 16-bit computation with it.
|
||||||
uint16_t cdata = input[i];
|
uint16_t cdata = input[i];
|
||||||
cdata = (cdata ^ crc) & 0xff;
|
cdata = (cdata ^ crc) & 0xff;
|
||||||
crc >>= 8;
|
crc >>= 8;
|
||||||
|
|
||||||
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
|
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
|
||||||
crc ^= 0xC001;
|
crc ^= 0xC001;
|
||||||
|
|
||||||
cdata <<= 6;
|
cdata <<= 6;
|
||||||
crc ^= cdata;
|
crc ^= cdata;
|
||||||
cdata <<= 1;
|
cdata <<= 1;
|
||||||
crc ^= cdata;
|
crc ^= cdata;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINO >= 100
|
#if ARDUINO >= 100
|
||||||
#include <Arduino.h> // for delayMicroseconds, digitalPinToBitMask, etc
|
#include <Arduino.h> // for delayMicroseconds, digitalPinToBitMask, etc
|
||||||
#else
|
#else
|
||||||
#include "WProgram.h" // for delayMicroseconds
|
#include "WProgram.h" // for delayMicroseconds
|
||||||
#include "pins_arduino.h" // for digitalPinToBitMask, etc
|
#include "pins_arduino.h" // for digitalPinToBitMask, etc
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// You can exclude certain features from OneWire. In theory, this
|
// You can exclude certain features from OneWire. In theory, this
|
||||||
@@ -52,37 +52,31 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Board-specific macros for direct GPIO
|
// Board-specific macros for direct GPIO
|
||||||
#include "OneWire_direct_regtype.h"
|
#include "util/OneWire_direct_regtype.h"
|
||||||
|
|
||||||
class OneWire {
|
class OneWire
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
IO_REG_TYPE bitmask;
|
IO_REG_TYPE bitmask;
|
||||||
volatile IO_REG_TYPE * baseReg;
|
volatile IO_REG_TYPE *baseReg;
|
||||||
|
|
||||||
#if ONEWIRE_SEARCH
|
#if ONEWIRE_SEARCH
|
||||||
// global search state
|
// global search state
|
||||||
unsigned char ROM_NO[8];
|
unsigned char ROM_NO[8];
|
||||||
uint8_t LastDiscrepancy;
|
uint8_t LastDiscrepancy;
|
||||||
uint8_t LastFamilyDiscrepancy;
|
uint8_t LastFamilyDiscrepancy;
|
||||||
bool LastDeviceFlag;
|
bool LastDeviceFlag;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OneWire() {
|
OneWire() { }
|
||||||
}
|
OneWire(uint8_t pin) { begin(pin); }
|
||||||
OneWire(uint8_t pin) {
|
|
||||||
begin(pin);
|
|
||||||
}
|
|
||||||
void begin(uint8_t pin);
|
void begin(uint8_t pin);
|
||||||
|
|
||||||
// Perform a 1-Wire reset cycle. Returns 1 if a device responds
|
// Perform a 1-Wire reset cycle. Returns 1 if a device responds
|
||||||
// with a presence pulse. Returns 0 if there is no device or the
|
// with a presence pulse. Returns 0 if there is no device or the
|
||||||
// bus is shorted or otherwise held low for more than 250uS
|
// bus is shorted or otherwise held low for more than 250uS
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
uint8_t IRAM_ATTR reset(void);
|
|
||||||
#else
|
|
||||||
uint8_t reset(void);
|
uint8_t reset(void);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Issue a 1-Wire rom select command, you do the reset first.
|
// Issue a 1-Wire rom select command, you do the reset first.
|
||||||
void select(const uint8_t rom[8]);
|
void select(const uint8_t rom[8]);
|
||||||
@@ -96,27 +90,20 @@ class OneWire {
|
|||||||
// another read or write.
|
// another read or write.
|
||||||
void write(uint8_t v, uint8_t power = 0);
|
void write(uint8_t v, uint8_t power = 0);
|
||||||
|
|
||||||
void write_bytes(const uint8_t * buf, uint16_t count, bool power = 0);
|
void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);
|
||||||
|
|
||||||
// Read a byte.
|
// Read a byte.
|
||||||
uint8_t read(void);
|
uint8_t read(void);
|
||||||
|
|
||||||
void read_bytes(uint8_t * buf, uint16_t count);
|
void read_bytes(uint8_t *buf, uint16_t count);
|
||||||
|
|
||||||
// Write a bit. The bus is always left powered at the end, see
|
// Write a bit. The bus is always left powered at the end, see
|
||||||
// note in write() about that.
|
// note in write() about that.
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
void write_bit(uint8_t v);
|
||||||
void IRAM_ATTR write_bit(uint8_t v);
|
|
||||||
#else
|
|
||||||
void write_bit(uint8_t v);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read a bit.
|
// Read a bit.
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
uint8_t IRAM_ATTR read_bit(void);
|
|
||||||
#else
|
|
||||||
uint8_t read_bit(void);
|
uint8_t read_bit(void);
|
||||||
#endif
|
|
||||||
// Stop forcing power onto the bus. You only need to do this if
|
// Stop forcing power onto the bus. You only need to do this if
|
||||||
// you used the 'power' flag to write() or used a write_bit() call
|
// you used the 'power' flag to write() or used a write_bit() call
|
||||||
// and aren't about to do another read or write. You would rather
|
// and aren't about to do another read or write. You would rather
|
||||||
@@ -138,13 +125,13 @@ class OneWire {
|
|||||||
// might be a good idea to check the CRC to make sure you didn't
|
// might be a good idea to check the CRC to make sure you didn't
|
||||||
// get garbage. The order is deterministic. You will always get
|
// get garbage. The order is deterministic. You will always get
|
||||||
// the same devices in the same order.
|
// the same devices in the same order.
|
||||||
bool search(uint8_t * newAddr, bool search_mode = true);
|
bool search(uint8_t *newAddr, bool search_mode = true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ONEWIRE_CRC
|
#if ONEWIRE_CRC
|
||||||
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the
|
// Compute a Dallas Semiconductor 8 bit CRC, these are used in the
|
||||||
// ROM and scratchpad registers.
|
// ROM and scratchpad registers.
|
||||||
static uint8_t crc8(const uint8_t * addr, uint8_t len);
|
static uint8_t crc8(const uint8_t *addr, uint8_t len);
|
||||||
|
|
||||||
#if ONEWIRE_CRC16
|
#if ONEWIRE_CRC16
|
||||||
// Compute the 1-Wire CRC16 and compare it against the received CRC.
|
// Compute the 1-Wire CRC16 and compare it against the received CRC.
|
||||||
@@ -167,7 +154,7 @@ class OneWire {
|
|||||||
// *not* at a 16-bit integer.
|
// *not* at a 16-bit integer.
|
||||||
// @param crc - The crc starting value (optional)
|
// @param crc - The crc starting value (optional)
|
||||||
// @return True, iff the CRC matches.
|
// @return True, iff the CRC matches.
|
||||||
static bool check_crc16(const uint8_t * input, uint16_t len, const uint8_t * inverted_crc, uint16_t crc = 0);
|
static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0);
|
||||||
|
|
||||||
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check
|
// Compute a Dallas Semiconductor 16 bit CRC. This is required to check
|
||||||
// the integrity of data received from many 1-Wire devices. Note that the
|
// the integrity of data received from many 1-Wire devices. Note that the
|
||||||
@@ -181,7 +168,7 @@ class OneWire {
|
|||||||
// @param len - How many bytes to use.
|
// @param len - How many bytes to use.
|
||||||
// @param crc - The crc starting value (optional)
|
// @param crc - The crc starting value (optional)
|
||||||
// @return The CRC16, as defined by Dallas Semiconductor.
|
// @return The CRC16, as defined by Dallas Semiconductor.
|
||||||
static uint16_t crc16(const uint8_t * input, uint16_t len, uint16_t crc = 0);
|
static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,409 +0,0 @@
|
|||||||
#ifndef OneWire_Direct_GPIO_h
|
|
||||||
#define OneWire_Direct_GPIO_h
|
|
||||||
|
|
||||||
// This header should ONLY be included by OneWire.cpp. These defines are
|
|
||||||
// meant to be private, used within OneWire.cpp, but not exposed to Arduino
|
|
||||||
// sketches or other libraries which may include OneWire.h.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Platform specific I/O definitions
|
|
||||||
|
|
||||||
#if defined(__AVR__)
|
|
||||||
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint8_t
|
|
||||||
#define IO_REG_BASE_ATTR asm("r30")
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#if defined(__AVR_ATmega4809__)
|
|
||||||
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) ((*((base)-8)) &= ~(mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)-8)) |= (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) ((*((base)-4)) &= ~(mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)-4)) |= (mask))
|
|
||||||
#else
|
|
||||||
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 1)) &= ~(mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 1)) |= (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 2)) &= ~(mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 2)) |= (mask))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
|
|
||||||
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
|
||||||
#define PIN_TO_BITMASK(pin) (1)
|
|
||||||
#define IO_REG_TYPE uint8_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR __attribute__((unused))
|
|
||||||
#define DIRECT_READ(base, mask) (*((base) + 512))
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) (*((base) + 640) = 0)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) (*((base) + 640) = 1)
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) (*((base) + 256) = 1)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) (*((base) + 128) = 1)
|
|
||||||
|
|
||||||
#elif defined(__MKL26Z64__)
|
|
||||||
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint8_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) ((*((base) + 16) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) (*((base) + 20) &= ~(mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) (*((base) + 20) |= (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) (*((base) + 8) = (mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) (*((base) + 4) = (mask))
|
|
||||||
|
|
||||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
|
||||||
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) ((*((base) + 2) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) (*((base) + 1) &= ~(mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) (*((base) + 1) |= (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) (*((base) + 34) = (mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) (*((base) + 33) = (mask))
|
|
||||||
|
|
||||||
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__)
|
|
||||||
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
|
|
||||||
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
|
|
||||||
// If you have trouble with OneWire on Arduino Due, please check the
|
|
||||||
// status of delayMicroseconds() before reporting a bug in OneWire!
|
|
||||||
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) (((*((base) + 15)) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 5)) = (mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 4)) = (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 13)) = (mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 12)) = (mask))
|
|
||||||
#ifndef PROGMEM
|
|
||||||
#define PROGMEM
|
|
||||||
#endif
|
|
||||||
#ifndef pgm_read_byte
|
|
||||||
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__PIC32MX__)
|
|
||||||
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) (((*(base + 4)) & (mask)) ? 1 : 0) //PORTX + 0x10
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) ((*(base + 2)) = (mask)) //TRISXSET + 0x08
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base + 1)) = (mask)) //TRISXCLR + 0x04
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) ((*(base + 8 + 1)) = (mask)) //LATXCLR + 0x24
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) ((*(base + 8 + 2)) = (mask)) //LATXSET + 0x28
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_ARCH_ESP8266)
|
|
||||||
// Special note: I depend on the ESP community to maintain these definitions and
|
|
||||||
// submit good pull requests. I can not answer any ESP questions or help you
|
|
||||||
// resolve any problems related to ESP chips. Please do not contact me and please
|
|
||||||
// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked
|
|
||||||
// on ESP community forums.
|
|
||||||
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)GPO)
|
|
||||||
#define PIN_TO_BITMASK(pin) (1 << pin)
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_ARCH_ESP32)
|
|
||||||
#include <driver/rtc_io.h>
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) (pin)
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE pin) {
|
|
||||||
if (pin < 32)
|
|
||||||
return (GPIO.in >> pin) & 0x1;
|
|
||||||
else if (pin < 40)
|
|
||||||
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE pin) {
|
|
||||||
if (pin < 32)
|
|
||||||
GPIO.out_w1tc = ((uint32_t)1 << pin);
|
|
||||||
else if (pin < 34)
|
|
||||||
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE pin) {
|
|
||||||
if (pin < 32)
|
|
||||||
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
|
||||||
else if (pin < 34)
|
|
||||||
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE pin) {
|
|
||||||
if (digitalPinIsValid(pin)) {
|
|
||||||
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
|
|
||||||
|
|
||||||
if (rtc_reg) // RTC pins PULL settings
|
|
||||||
{
|
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin < 32)
|
|
||||||
GPIO.enable_w1tc = ((uint32_t)1 << pin);
|
|
||||||
else
|
|
||||||
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
|
||||||
|
|
||||||
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
|
||||||
pinFunction |= FUN_IE; // input enable but required for output as well?
|
|
||||||
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
|
|
||||||
|
|
||||||
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
|
||||||
|
|
||||||
GPIO.pin[pin].val = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE pin) {
|
|
||||||
if (digitalPinIsValid(pin) && pin <= 33) // pins above 33 can be only inputs
|
|
||||||
{
|
|
||||||
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
|
|
||||||
|
|
||||||
if (rtc_reg) // RTC pins PULL settings
|
|
||||||
{
|
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
|
||||||
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pin < 32)
|
|
||||||
GPIO.enable_w1ts = ((uint32_t)1 << pin);
|
|
||||||
else // already validated to pins <= 33
|
|
||||||
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
|
||||||
|
|
||||||
uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
|
|
||||||
pinFunction |= FUN_IE; // input enable but required for output as well?
|
|
||||||
pinFunction |= ((uint32_t)2 << MCU_SEL_S);
|
|
||||||
|
|
||||||
ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;
|
|
||||||
|
|
||||||
GPIO.pin[pin].val = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DIRECT_READ(base, pin) directRead(pin)
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin)
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin)
|
|
||||||
// https://github.com/PaulStoffregen/OneWire/pull/47
|
|
||||||
// https://github.com/stickbreaker/OneWire/commit/6eb7fc1c11a15b6ac8c60e5671cf36eb6829f82c
|
|
||||||
#ifdef interrupts
|
|
||||||
#undef interrupts
|
|
||||||
#endif
|
|
||||||
#ifdef noInterrupts
|
|
||||||
#undef noInterrupts
|
|
||||||
#endif
|
|
||||||
#define noInterrupts() \
|
|
||||||
{ \
|
|
||||||
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; \
|
|
||||||
portENTER_CRITICAL(&mux)
|
|
||||||
#define interrupts() \
|
|
||||||
portEXIT_CRITICAL(&mux); \
|
|
||||||
}
|
|
||||||
//#warning "ESP32 OneWire testing"
|
|
||||||
|
|
||||||
#elif defined(ARDUINO_ARCH_STM32)
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) ((uint32_t)digitalPinToPinName(pin))
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, pin) digitalReadFast((PinName)pin)
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) digitalWriteFast((PinName)pin, LOW)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) digitalWriteFast((PinName)pin, HIGH)
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0))
|
|
||||||
|
|
||||||
#elif defined(__SAMD21G18A__)
|
|
||||||
#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin))
|
|
||||||
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, mask) (((*((base) + 8)) & (mask)) ? 1 : 0)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) ((*((base) + 1)) = (mask))
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base) + 2)) = (mask))
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) ((*((base) + 5)) = (mask))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) ((*((base) + 6)) = (mask))
|
|
||||||
|
|
||||||
#elif defined(__ASR6501__)
|
|
||||||
#define PIN_IN_PORT(pin) (pin % PIN_NUMBER_IN_PORT)
|
|
||||||
#define PORT_FROM_PIN(pin) (pin / PIN_NUMBER_IN_PORT)
|
|
||||||
#define PORT_OFFSET(port) (PORT_REG_SHFIT * port)
|
|
||||||
#define PORT_ADDRESS(pin) (CYDEV_GPIO_BASE + PORT_OFFSET(PORT_FROM_PIN(pin)))
|
|
||||||
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) (pin)
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, pin) CY_SYS_PINS_READ_PIN(PORT_ADDRESS(pin) + 4, PIN_IN_PORT(pin))
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) CY_SYS_PINS_CLEAR_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) CY_SYS_PINS_SET_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin) + 8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_DIG_HIZ)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin) + 8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_STRONG)
|
|
||||||
|
|
||||||
#elif defined(RBL_NRF51822)
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) (pin)
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin)
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin)
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin)
|
|
||||||
|
|
||||||
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
|
|
||||||
|
|
||||||
#include "scss_registers.h"
|
|
||||||
#include "portable.h"
|
|
||||||
#include "avr/pgmspace.h"
|
|
||||||
|
|
||||||
#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId)
|
|
||||||
#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType)
|
|
||||||
#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase)
|
|
||||||
#define DIR_OFFSET_SS 0x01
|
|
||||||
#define DIR_OFFSET_SOC 0x04
|
|
||||||
#define EXT_PORT_OFFSET_SS 0x0A
|
|
||||||
#define EXT_PORT_OFFSET_SOC 0x50
|
|
||||||
|
|
||||||
/* GPIO registers base address */
|
|
||||||
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase)
|
|
||||||
#define PIN_TO_BITMASK(pin) pin
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
|
|
||||||
IO_REG_TYPE ret;
|
|
||||||
if (SS_GPIO == GPIO_TYPE(pin)) {
|
|
||||||
ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS));
|
|
||||||
} else {
|
|
||||||
ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC);
|
|
||||||
}
|
|
||||||
return ((ret >> GPIO_ID(pin)) & 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeInput(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
|
|
||||||
if (SS_GPIO == GPIO_TYPE(pin)) {
|
|
||||||
WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), ((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
|
|
||||||
} else {
|
|
||||||
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeOutput(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
|
|
||||||
if (SS_GPIO == GPIO_TYPE(pin)) {
|
|
||||||
WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), ((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
|
|
||||||
} else {
|
|
||||||
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteLow(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
|
|
||||||
if (SS_GPIO == GPIO_TYPE(pin)) {
|
|
||||||
WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base);
|
|
||||||
} else {
|
|
||||||
MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteHigh(volatile IO_REG_TYPE * base, IO_REG_TYPE pin) {
|
|
||||||
if (SS_GPIO == GPIO_TYPE(pin)) {
|
|
||||||
WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base);
|
|
||||||
} else {
|
|
||||||
MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DIRECT_READ(base, pin) directRead(base, pin)
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin)
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin)
|
|
||||||
|
|
||||||
#elif defined(__riscv)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tested on highfive1
|
|
||||||
*
|
|
||||||
* Stable results are achieved operating in the
|
|
||||||
* two high speed modes of the highfive1. It
|
|
||||||
* seems to be less reliable in slow mode.
|
|
||||||
*/
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin)
|
|
||||||
#define IO_REG_TYPE uint32_t
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) IO_REG_TYPE directRead(IO_REG_TYPE mask) {
|
|
||||||
return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeInput(IO_REG_TYPE mask) {
|
|
||||||
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
|
|
||||||
GPIO_REG(GPIO_IOF_EN) &= ~mask;
|
|
||||||
|
|
||||||
GPIO_REG(GPIO_INPUT_EN) |= mask;
|
|
||||||
GPIO_REG(GPIO_OUTPUT_EN) &= ~mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directModeOutput(IO_REG_TYPE mask) {
|
|
||||||
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
|
|
||||||
GPIO_REG(GPIO_IOF_EN) &= ~mask;
|
|
||||||
|
|
||||||
GPIO_REG(GPIO_INPUT_EN) &= ~mask;
|
|
||||||
GPIO_REG(GPIO_OUTPUT_EN) |= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteLow(IO_REG_TYPE mask) {
|
|
||||||
GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void directWriteHigh(IO_REG_TYPE mask) {
|
|
||||||
GPIO_REG(GPIO_OUTPUT_VAL) |= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DIRECT_READ(base, mask) directRead(mask)
|
|
||||||
#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask)
|
|
||||||
#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask)
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define PIN_TO_BASEREG(pin) (0)
|
|
||||||
#define PIN_TO_BITMASK(pin) (pin)
|
|
||||||
#define IO_REG_TYPE unsigned int
|
|
||||||
#define IO_REG_BASE_ATTR
|
|
||||||
#define IO_REG_MASK_ATTR
|
|
||||||
#define DIRECT_READ(base, pin) digitalRead(pin)
|
|
||||||
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
|
|
||||||
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
|
|
||||||
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin, INPUT)
|
|
||||||
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin, OUTPUT)
|
|
||||||
#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
445
lib/OneWire/util/OneWire_direct_gpio.h
Normal file
445
lib/OneWire/util/OneWire_direct_gpio.h
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
#ifndef OneWire_Direct_GPIO_h
|
||||||
|
#define OneWire_Direct_GPIO_h
|
||||||
|
|
||||||
|
// This header should ONLY be included by OneWire.cpp. These defines are
|
||||||
|
// meant to be private, used within OneWire.cpp, but not exposed to Arduino
|
||||||
|
// sketches or other libraries which may include OneWire.h.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Platform specific I/O definitions
|
||||||
|
|
||||||
|
#if defined(__AVR__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_BASE_ATTR asm("r30")
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#if defined(__AVR_ATmega4809__)
|
||||||
|
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)-8)) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)-8)) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)-4)) &= ~(mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)-4)) |= (mask))
|
||||||
|
#else
|
||||||
|
#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (1)
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR __attribute__ ((unused))
|
||||||
|
#define DIRECT_READ(base, mask) (*((base)+512))
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1)
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1)
|
||||||
|
|
||||||
|
#elif defined(__MKL26Z64__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint8_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask))
|
||||||
|
|
||||||
|
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) ((*((base)+2) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (*((base)+1) &= ~(mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+1) |= (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (*((base)+34) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+33) = (mask))
|
||||||
|
|
||||||
|
#elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__)
|
||||||
|
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
|
||||||
|
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
|
||||||
|
// If you have trouble with OneWire on Arduino Due, please check the
|
||||||
|
// status of delayMicroseconds() before reporting a bug in OneWire!
|
||||||
|
#define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask))
|
||||||
|
#ifndef PROGMEM
|
||||||
|
#define PROGMEM
|
||||||
|
#endif
|
||||||
|
#ifndef pgm_read_byte
|
||||||
|
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__PIC32MX__)
|
||||||
|
#define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin)))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28
|
||||||
|
|
||||||
|
#elif defined(ARDUINO_ARCH_ESP8266)
|
||||||
|
// Special note: I depend on the ESP community to maintain these definitions and
|
||||||
|
// submit good pull requests. I can not answer any ESP questions or help you
|
||||||
|
// resolve any problems related to ESP chips. Please do not contact me and please
|
||||||
|
// DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked
|
||||||
|
// on ESP community forums.
|
||||||
|
#define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO)
|
||||||
|
#define PIN_TO_BITMASK(pin) (1 << pin)
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS
|
||||||
|
|
||||||
|
#elif defined(ARDUINO_ARCH_ESP32)
|
||||||
|
#include <driver/rtc_io.h>
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) (pin)
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
IO_REG_TYPE directRead(IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
return (GPIO.in.val >> pin) & 0x1;
|
||||||
|
#else // plain ESP32
|
||||||
|
if ( pin < 32 )
|
||||||
|
return (GPIO.in >> pin) & 0x1;
|
||||||
|
else if ( pin < 46 )
|
||||||
|
return (GPIO.in1.val >> (pin - 32)) & 0x1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteLow(IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
GPIO.out_w1tc.val = ((uint32_t)1 << pin);
|
||||||
|
#else // plain ESP32
|
||||||
|
if ( pin < 32 )
|
||||||
|
GPIO.out_w1tc = ((uint32_t)1 << pin);
|
||||||
|
else if ( pin < 46 )
|
||||||
|
GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteHigh(IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
GPIO.out_w1ts.val = ((uint32_t)1 << pin);
|
||||||
|
#else // plain ESP32
|
||||||
|
if ( pin < 32 )
|
||||||
|
GPIO.out_w1ts = ((uint32_t)1 << pin);
|
||||||
|
else if ( pin < 46 )
|
||||||
|
GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeInput(IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
GPIO.enable_w1tc.val = ((uint32_t)1 << (pin));
|
||||||
|
#else
|
||||||
|
if ( digitalPinIsValid(pin) )
|
||||||
|
{
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
|
||||||
|
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
|
||||||
|
|
||||||
|
if ( rtc_reg ) // RTC pins PULL settings
|
||||||
|
{
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Input
|
||||||
|
if ( pin < 32 )
|
||||||
|
GPIO.enable_w1tc = ((uint32_t)1 << pin);
|
||||||
|
else
|
||||||
|
GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeOutput(IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
GPIO.enable_w1ts.val = ((uint32_t)1 << (pin));
|
||||||
|
#else
|
||||||
|
if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs
|
||||||
|
{
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 4 // IDF 3.x ESP32/PICO-D4
|
||||||
|
uint32_t rtc_reg(rtc_gpio_desc[pin].reg);
|
||||||
|
|
||||||
|
if ( rtc_reg ) // RTC pins PULL settings
|
||||||
|
{
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
|
||||||
|
ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Output
|
||||||
|
if ( pin < 32 )
|
||||||
|
GPIO.enable_w1ts = ((uint32_t)1 << pin);
|
||||||
|
else // already validated to pins <= 33
|
||||||
|
GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DIRECT_READ(base, pin) directRead(pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) directModeInput(pin)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin)
|
||||||
|
// https://github.com/PaulStoffregen/OneWire/pull/47
|
||||||
|
// https://github.com/stickbreaker/OneWire/commit/6eb7fc1c11a15b6ac8c60e5671cf36eb6829f82c
|
||||||
|
#ifdef interrupts
|
||||||
|
#undef interrupts
|
||||||
|
#endif
|
||||||
|
#ifdef noInterrupts
|
||||||
|
#undef noInterrupts
|
||||||
|
#endif
|
||||||
|
#define noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux)
|
||||||
|
#define interrupts() portEXIT_CRITICAL(&mux);}
|
||||||
|
//#warning "ESP32 OneWire testing"
|
||||||
|
|
||||||
|
#elif defined(ARDUINO_ARCH_STM32)
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) ((uint32_t)digitalPinToPinName(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, pin) digitalReadFast((PinName)pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) digitalWriteFast((PinName)pin, LOW)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) digitalWriteFast((PinName)pin, HIGH)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) pin_function((PinName)pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0))
|
||||||
|
|
||||||
|
#elif defined(__SAMD21G18A__)
|
||||||
|
#define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin))
|
||||||
|
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask))
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask))
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask))
|
||||||
|
|
||||||
|
#elif defined(__ASR6501__)
|
||||||
|
#define PIN_IN_PORT(pin) (pin % PIN_NUMBER_IN_PORT)
|
||||||
|
#define PORT_FROM_PIN(pin) (pin / PIN_NUMBER_IN_PORT)
|
||||||
|
#define PORT_OFFSET(port) (PORT_REG_SHFIT * port)
|
||||||
|
#define PORT_ADDRESS(pin) (CYDEV_GPIO_BASE + PORT_OFFSET(PORT_FROM_PIN(pin)))
|
||||||
|
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) (pin)
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, pin) CY_SYS_PINS_READ_PIN(PORT_ADDRESS(pin)+4, PIN_IN_PORT(pin))
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) CY_SYS_PINS_CLEAR_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) CY_SYS_PINS_SET_PIN(PORT_ADDRESS(pin), PIN_IN_PORT(pin))
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_DIG_HIZ)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) CY_SYS_PINS_SET_DRIVE_MODE(PORT_ADDRESS(pin)+8, PIN_IN_PORT(pin), CY_SYS_PINS_DM_STRONG)
|
||||||
|
|
||||||
|
#elif defined(RBL_NRF51822)
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) (pin)
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin)
|
||||||
|
|
||||||
|
#elif defined(__arc__) /* Arduino101/Genuino101 specifics */
|
||||||
|
|
||||||
|
#include "scss_registers.h"
|
||||||
|
#include "portable.h"
|
||||||
|
#include "avr/pgmspace.h"
|
||||||
|
|
||||||
|
#define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId)
|
||||||
|
#define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType)
|
||||||
|
#define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase)
|
||||||
|
#define DIR_OFFSET_SS 0x01
|
||||||
|
#define DIR_OFFSET_SOC 0x04
|
||||||
|
#define EXT_PORT_OFFSET_SS 0x0A
|
||||||
|
#define EXT_PORT_OFFSET_SOC 0x50
|
||||||
|
|
||||||
|
/* GPIO registers base address */
|
||||||
|
#define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase)
|
||||||
|
#define PIN_TO_BITMASK(pin) pin
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
IO_REG_TYPE ret;
|
||||||
|
if (SS_GPIO == GPIO_TYPE(pin)) {
|
||||||
|
ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS));
|
||||||
|
} else {
|
||||||
|
ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC);
|
||||||
|
}
|
||||||
|
return ((ret >> GPIO_ID(pin)) & 0x01);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
if (SS_GPIO == GPIO_TYPE(pin)) {
|
||||||
|
WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)),
|
||||||
|
((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
|
||||||
|
} else {
|
||||||
|
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
if (SS_GPIO == GPIO_TYPE(pin)) {
|
||||||
|
WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)),
|
||||||
|
((IO_REG_TYPE)(base) + DIR_OFFSET_SS));
|
||||||
|
} else {
|
||||||
|
MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
if (SS_GPIO == GPIO_TYPE(pin)) {
|
||||||
|
WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base);
|
||||||
|
} else {
|
||||||
|
MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin)
|
||||||
|
{
|
||||||
|
if (SS_GPIO == GPIO_TYPE(pin)) {
|
||||||
|
WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base);
|
||||||
|
} else {
|
||||||
|
MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DIRECT_READ(base, pin) directRead(base, pin)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin)
|
||||||
|
|
||||||
|
#elif defined(__riscv)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tested on highfive1
|
||||||
|
*
|
||||||
|
* Stable results are achieved operating in the
|
||||||
|
* two high speed modes of the highfive1. It
|
||||||
|
* seems to be less reliable in slow mode.
|
||||||
|
*/
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin)
|
||||||
|
#define IO_REG_TYPE uint32_t
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
IO_REG_TYPE directRead(IO_REG_TYPE mask)
|
||||||
|
{
|
||||||
|
return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeInput(IO_REG_TYPE mask)
|
||||||
|
{
|
||||||
|
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
|
||||||
|
GPIO_REG(GPIO_IOF_EN) &= ~mask;
|
||||||
|
|
||||||
|
GPIO_REG(GPIO_INPUT_EN) |= mask;
|
||||||
|
GPIO_REG(GPIO_OUTPUT_EN) &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directModeOutput(IO_REG_TYPE mask)
|
||||||
|
{
|
||||||
|
GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask;
|
||||||
|
GPIO_REG(GPIO_IOF_EN) &= ~mask;
|
||||||
|
|
||||||
|
GPIO_REG(GPIO_INPUT_EN) &= ~mask;
|
||||||
|
GPIO_REG(GPIO_OUTPUT_EN) |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteLow(IO_REG_TYPE mask)
|
||||||
|
{
|
||||||
|
GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((always_inline))
|
||||||
|
void directWriteHigh(IO_REG_TYPE mask)
|
||||||
|
{
|
||||||
|
GPIO_REG(GPIO_OUTPUT_VAL) |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DIRECT_READ(base, mask) directRead(mask)
|
||||||
|
#define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask)
|
||||||
|
#define DIRECT_MODE_INPUT(base, mask) directModeInput(mask)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define PIN_TO_BASEREG(pin) (0)
|
||||||
|
#define PIN_TO_BITMASK(pin) (pin)
|
||||||
|
#define IO_REG_TYPE unsigned int
|
||||||
|
#define IO_REG_BASE_ATTR
|
||||||
|
#define IO_REG_MASK_ATTR
|
||||||
|
#define DIRECT_READ(base, pin) digitalRead(pin)
|
||||||
|
#define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW)
|
||||||
|
#define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH)
|
||||||
|
#define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT)
|
||||||
|
#define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT)
|
||||||
|
#warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture."
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -47,7 +47,7 @@ void APSettingsService::manageAP() {
|
|||||||
|
|
||||||
void APSettingsService::startAP() {
|
void APSettingsService::startAP() {
|
||||||
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
||||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_AP, WIFI_BW_HT20);
|
||||||
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
||||||
if (!_dnsServer) {
|
if (!_dnsServer) {
|
||||||
IPAddress apIp = WiFi.softAPIP();
|
IPAddress apIp = WiFi.softAPIP();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void FactoryResetService::handleRequest(AsyncWebServerRequest * request) {
|
|||||||
*/
|
*/
|
||||||
void FactoryResetService::factoryReset() {
|
void FactoryResetService::factoryReset() {
|
||||||
/*
|
/*
|
||||||
* Based on LITTLEFS. Modified by proddy
|
* Based on LittleFS. Modified by proddy
|
||||||
* Could be replaced with fs.rmdir(FS_CONFIG_DIRECTORY) in IDF 4.2
|
* Could be replaced with fs.rmdir(FS_CONFIG_DIRECTORY) in IDF 4.2
|
||||||
*/
|
*/
|
||||||
File root = fs->open(FS_CONFIG_DIRECTORY);
|
File root = fs->open(FS_CONFIG_DIRECTORY);
|
||||||
|
|||||||
@@ -99,23 +99,17 @@ void MqttSettingsService::onConfigUpdated() {
|
|||||||
|
|
||||||
void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SYSTEM_EVENT_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
emsesp::EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||||
if (!networkSettings.enableIPv6 && _state.enabled) {
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
// emsesp::EMSESP::logger().info(F("IPv4 Network connection found, starting MQTT client"));
|
|
||||||
onConfigUpdated();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case SYSTEM_EVENT_GOT_IP6:
|
|
||||||
if (_state.enabled) {
|
if (_state.enabled) {
|
||||||
// emsesp::EMSESP::logger().info(F("IPv6 Network connection found, starting MQTT client"));
|
// emsesp::EMSESP::logger().info(F("Network connection found, starting MQTT client"));
|
||||||
onConfigUpdated();
|
onConfigUpdated();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
if (_state.enabled) {
|
if (_state.enabled) {
|
||||||
// emsesp::EMSESP::logger().info(F("Network connection dropped, stopping MQTT client"));
|
// emsesp::EMSESP::logger().info(F("Network connection dropped, stopping MQTT client"));
|
||||||
_mqttClient.disconnect();
|
_mqttClient.disconnect();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <NTPSettingsService.h>
|
#include <NTPSettingsService.h>
|
||||||
|
#include <esp_sntp.h>
|
||||||
|
|
||||||
#include "../../src/emsesp_stub.hpp" // proddy added
|
#include "../../src/emsesp_stub.hpp" // proddy added
|
||||||
|
|
||||||
@@ -25,15 +26,15 @@ void NTPSettingsService::begin() {
|
|||||||
// handles both WiFI and Ethernet
|
// handles both WiFI and Ethernet
|
||||||
void NTPSettingsService::WiFiEvent(WiFiEvent_t event) {
|
void NTPSettingsService::WiFiEvent(WiFiEvent_t event) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
emsesp::EMSESP::logger().info(F("WiFi connection dropped, stopping NTP"));
|
emsesp::EMSESP::logger().info(F("WiFi connection dropped, stopping NTP"));
|
||||||
connected_ = false;
|
connected_ = false;
|
||||||
configureNTP();
|
configureNTP();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYSTEM_EVENT_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
// emsesp::EMSESP::logger().info(F("Got IP address, starting NTP synchronization"));
|
// emsesp::EMSESP::logger().info(F("Got IP address, starting NTP synchronization"));
|
||||||
connected_ = true;
|
connected_ = true;
|
||||||
configureNTP();
|
configureNTP();
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ void NetworkSettingsService::manageSTA() {
|
|||||||
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
||||||
if (_state.staticIPConfig) {
|
if (_state.staticIPConfig) {
|
||||||
WiFi.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2); // configure for static IP
|
WiFi.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2); // configure for static IP
|
||||||
} else {
|
|
||||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); // configure for DHCP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFi.setHostname(_state.hostname.c_str()); // set hostname
|
WiFi.setHostname(_state.hostname.c_str()); // set hostname
|
||||||
@@ -66,9 +64,9 @@ void NetworkSettingsService::manageSTA() {
|
|||||||
// www.esp32.com/viewtopic.php?t=12055
|
// www.esp32.com/viewtopic.php?t=12055
|
||||||
read([&](NetworkSettings & networkSettings) {
|
read([&](NetworkSettings & networkSettings) {
|
||||||
if (networkSettings.bandwidth20) {
|
if (networkSettings.bandwidth20) {
|
||||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT20);
|
esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_STA, WIFI_BW_HT20);
|
||||||
} else {
|
} else {
|
||||||
esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT40);
|
esp_wifi_set_bandwidth((wifi_interface_t)ESP_IF_WIFI_STA, WIFI_BW_HT40);
|
||||||
}
|
}
|
||||||
esp_wifi_set_max_tx_power(networkSettings.tx_power * 4);
|
esp_wifi_set_max_tx_power(networkSettings.tx_power * 4);
|
||||||
if (networkSettings.nosleep) {
|
if (networkSettings.nosleep) {
|
||||||
@@ -82,7 +80,7 @@ void NetworkSettingsService::manageSTA() {
|
|||||||
|
|
||||||
// handles if wifi stopped
|
// handles if wifi stopped
|
||||||
void NetworkSettingsService::WiFiEvent(WiFiEvent_t event) {
|
void NetworkSettingsService::WiFiEvent(WiFiEvent_t event) {
|
||||||
if (event == SYSTEM_EVENT_STA_STOP) {
|
if (event == ARDUINO_EVENT_WIFI_STA_STOP) {
|
||||||
if (_stopping) {
|
if (_stopping) {
|
||||||
_lastConnectionAttempt = 0;
|
_lastConnectionAttempt = 0;
|
||||||
_stopping = false;
|
_stopping = false;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#define NETWORK_SETTINGS_FILE "/config/networkSettings.json"
|
#define NETWORK_SETTINGS_FILE "/config/networkSettings.json"
|
||||||
#define NETWORK_SETTINGS_SERVICE_PATH "/rest/networkSettings"
|
#define NETWORK_SETTINGS_SERVICE_PATH "/rest/networkSettings"
|
||||||
#define WIFI_RECONNECTION_DELAY 1000 * 30
|
#define WIFI_RECONNECTION_DELAY 1000 * 3
|
||||||
|
|
||||||
#ifndef FACTORY_WIFI_SSID
|
#ifndef FACTORY_WIFI_SSID
|
||||||
#define FACTORY_WIFI_SSID ""
|
#define FACTORY_WIFI_SSID ""
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ void OTASettingsService::configureArduinoOTA() {
|
|||||||
|
|
||||||
void OTASettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void OTASettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case SYSTEM_EVENT_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
configureArduinoOTA();
|
configureArduinoOTA();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FS_BUFFER_SIZE
|
#ifndef FS_BUFFER_SIZE
|
||||||
#define FS_BUFFER_SIZE 4096
|
#define FS_BUFFER_SIZE 8192
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class StateUpdateResult {
|
enum class StateUpdateResult {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ void SystemStatus::systemStatus(AsyncWebServerRequest * request) {
|
|||||||
root["flash_chip_size"] = ESP.getFlashChipSize();
|
root["flash_chip_size"] = ESP.getFlashChipSize();
|
||||||
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
|
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
|
||||||
|
|
||||||
root["fs_total"] = LITTLEFS.totalBytes();
|
root["fs_total"] = LittleFS.totalBytes();
|
||||||
root["fs_used"] = LITTLEFS.usedBytes();
|
root["fs_used"] = LittleFS.usedBytes();
|
||||||
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <LITTLEFS.h>
|
#include <LittleFS.h>
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
|||||||
@@ -28,8 +28,10 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
|||||||
std::string extension = fname.substr(position + 1);
|
std::string extension = fname.substr(position + 1);
|
||||||
size_t fsize = request->contentLength();
|
size_t fsize = request->contentLength();
|
||||||
|
|
||||||
|
#if defined(EMSESP_USE_SERIAL)
|
||||||
Serial.printf("Received filename: %s, len: %d, index: %d, ext: %s, fsize: %d", filename.c_str(), len, index, extension.c_str(), fsize);
|
Serial.printf("Received filename: %s, len: %d, index: %d, ext: %s, fsize: %d", filename.c_str(), len, index, extension.c_str(), fsize);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((extension == "bin") && (fsize > 1500000)) {
|
if ((extension == "bin") && (fsize > 1500000)) {
|
||||||
is_firmware = true;
|
is_firmware = true;
|
||||||
@@ -52,7 +54,7 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// its a normal file, open a new temp file to write the contents too
|
// its a normal file, open a new temp file to write the contents too
|
||||||
request->_tempFile = LITTLEFS.open(TEMP_FILENAME_PATH, "w");
|
request->_tempFile = LittleFS.open(TEMP_FILENAME_PATH, "w");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
#include <LITTLEFS.h>
|
#include <LittleFS.h>
|
||||||
|
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <SecurityManager.h>
|
#include <SecurityManager.h>
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ void SyslogService::remove_queued_messages(uuid::log::Level level) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_message_id_ -= offset;
|
log_message_id_ -= offset;
|
||||||
|
log_message_fails_ += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyslogService::log_level(uuid::log::Level level) {
|
void SyslogService::log_level(uuid::log::Level level) {
|
||||||
@@ -232,6 +233,7 @@ void SyslogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
|||||||
if (log_messages_.size() >= maximum_log_messages_) {
|
if (log_messages_.size() >= maximum_log_messages_) {
|
||||||
log_messages_overflow_ = true;
|
log_messages_overflow_ = true;
|
||||||
log_messages_.pop_front();
|
log_messages_.pop_front();
|
||||||
|
log_message_fails_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_messages_.emplace_back(log_message_id_++, std::move(message));
|
log_messages_.emplace_back(log_message_id_++, std::move(message));
|
||||||
|
|||||||
@@ -198,6 +198,13 @@ class SyslogService : public uuid::log::Handler {
|
|||||||
return ip_;
|
return ip_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long message_count() {
|
||||||
|
return log_message_id_;
|
||||||
|
}
|
||||||
|
unsigned long message_fails() {
|
||||||
|
return log_message_fails_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Log message that has been queued.
|
* Log message that has been queued.
|
||||||
@@ -268,8 +275,9 @@ class SyslogService : public uuid::log::Handler {
|
|||||||
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 1.0.0 */
|
unsigned long log_message_id_ = 0; /*!< The next identifier to use for queued log messages. @since 1.0.0 */
|
||||||
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 1.0.0 */
|
std::list<QueuedLogMessage> log_messages_; /*!< Queued log messages, in the order they were received. @since 1.0.0 */
|
||||||
std::atomic<bool> log_messages_overflow_{false}; /*!< Check if log messages have overflowed the buffer. @since 1.0.0 */
|
std::atomic<bool> log_messages_overflow_{false}; /*!< Check if log messages have overflowed the buffer. @since 1.0.0 */
|
||||||
uint64_t mark_interval_ = 0; /*!< Mark interval in milliseconds. @since 2.0.0 */
|
uint64_t mark_interval_ = 0; /*!< Mark interval in milliseconds. @since 2.0.0 */
|
||||||
uint64_t last_message_ = 0; /*!< Last message/mark time. @since 2.0.0 */
|
uint64_t last_message_ = 0; /*!< Last message/mark time. @since 2.0.0 */
|
||||||
|
unsigned long log_message_fails_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace syslog
|
} // namespace syslog
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class DummySettings {
|
|||||||
uint32_t syslog_mark_interval = 0;
|
uint32_t syslog_mark_interval = 0;
|
||||||
String syslog_host = "192.168.1.4";
|
String syslog_host = "192.168.1.4";
|
||||||
uint16_t syslog_port = 514;
|
uint16_t syslog_port = 514;
|
||||||
uint8_t master_thermostat = 0;
|
|
||||||
bool shower_timer = true;
|
bool shower_timer = true;
|
||||||
bool shower_alert = false;
|
bool shower_alert = false;
|
||||||
uint8_t shower_alert_coldshot = 10;
|
uint8_t shower_alert_coldshot = 10;
|
||||||
|
|||||||
@@ -20,34 +20,35 @@ typedef enum {
|
|||||||
typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t;
|
typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_MAX } eth_phy_type_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
|
ARDUINO_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
|
||||||
SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
|
ARDUINO_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
|
||||||
SYSTEM_EVENT_STA_START, /**< ESP32 station start */
|
ARDUINO_EVENT_WIFI_STA_START, /**< ESP32 station start */
|
||||||
SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */
|
ARDUINO_EVENT_WIFI_STA_STOP, /**< ESP32 station stop */
|
||||||
SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
|
ARDUINO_EVENT_WIFI_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||||
SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
ARDUINO_EVENT_WIFI_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
||||||
SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
|
ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
|
||||||
SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */
|
ARDUINO_EVENT_WIFI_STA_GOT_IP, /**< ESP32 station got IP from connected AP */
|
||||||
SYSTEM_EVENT_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */
|
ARDUINO_EVENT_WIFI_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
|
ARDUINO_EVENT_WIFI_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
|
ARDUINO_EVENT_WIFI_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
|
ARDUINO_EVENT_WIFI_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
|
ARDUINO_EVENT_WIFI_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
|
||||||
SYSTEM_EVENT_STA_WPS_ER_PBC_OVERLAP, /*!< ESP32 station wps overlap in enrollee mode */
|
ARDUINO_EVENT_WIFI_STA_WPS_ER_PBC_OVERLAP, /*!< ESP32 station wps overlap in enrollee mode */
|
||||||
SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */
|
ARDUINO_EVENT_WIFI_AP_START, /**< ESP32 soft-AP start */
|
||||||
SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
|
ARDUINO_EVENT_WIFI_AP_STOP, /**< ESP32 soft-AP stop */
|
||||||
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
|
ARDUINO_EVENT_WIFI_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
|
||||||
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
|
ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
|
||||||
SYSTEM_EVENT_AP_STAIPASSIGNED, /**< ESP32 soft-AP assign an IP to a connected station */
|
ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED, /**< ESP32 soft-AP assign an IP to a connected station */
|
||||||
SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
|
ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
|
||||||
SYSTEM_EVENT_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
|
ARDUINO_EVENT_WIFI_STA_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
|
||||||
SYSTEM_EVENT_ETH_START, /**< ESP32 ethernet start */
|
ARDUINO_EVENT_ETH_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
|
||||||
SYSTEM_EVENT_ETH_STOP, /**< ESP32 ethernet stop */
|
ARDUINO_EVENT_ETH_START, /**< ESP32 ethernet start */
|
||||||
SYSTEM_EVENT_ETH_CONNECTED, /**< ESP32 ethernet phy link up */
|
ARDUINO_EVENT_ETH_STOP, /**< ESP32 ethernet stop */
|
||||||
SYSTEM_EVENT_ETH_DISCONNECTED, /**< ESP32 ethernet phy link down */
|
ARDUINO_EVENT_ETH_CONNECTED, /**< ESP32 ethernet phy link up */
|
||||||
SYSTEM_EVENT_ETH_GOT_IP, /**< ESP32 ethernet got IP from connected AP */
|
ARDUINO_EVENT_ETH_DISCONNECTED, /**< ESP32 ethernet phy link down */
|
||||||
SYSTEM_EVENT_MAX
|
ARDUINO_EVENT_ETH_GOT_IP, /**< ESP32 ethernet got IP from connected AP */
|
||||||
} system_event_id_t;
|
ARDUINO_EVENT_MAX
|
||||||
|
} arduino_event_id_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
|
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
|
||||||
@@ -60,74 +61,60 @@ typedef enum {
|
|||||||
} wifi_auth_mode_t;
|
} wifi_auth_mode_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t status; /**< status of scanning APs */
|
uint32_t status; /**< status of scanning APs: 0 — success, 1 - failure */
|
||||||
uint8_t number;
|
uint8_t number; /**< number of scan results */
|
||||||
uint8_t scan_id;
|
uint8_t scan_id; /**< scan sequence number, used for block scan */
|
||||||
} system_event_sta_scan_done_t;
|
} wifi_event_sta_scan_done_t;
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_CONNECTED event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ssid[32]; /**< SSID of connected AP */
|
uint8_t ssid[32]; /**< SSID of connected AP */
|
||||||
uint8_t ssid_len; /**< SSID length of connected AP */
|
uint8_t ssid_len; /**< SSID length of connected AP */
|
||||||
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
||||||
uint8_t channel; /**< channel of connected AP*/
|
uint8_t channel; /**< channel of connected AP*/
|
||||||
wifi_auth_mode_t authmode;
|
wifi_auth_mode_t authmode;/**< authentication mode used by AP*/
|
||||||
} system_event_sta_connected_t;
|
} wifi_event_sta_connected_t;
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
||||||
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
||||||
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
||||||
uint8_t reason; /**< reason of disconnection */
|
uint8_t reason; /**< reason of disconnection */
|
||||||
} system_event_sta_disconnected_t;
|
} wifi_event_sta_disconnected_t;
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
||||||
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
||||||
} system_event_sta_authmode_change_t;
|
} wifi_event_sta_authmode_change_t;
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
||||||
} system_event_sta_wps_er_pin_t;
|
} wifi_event_sta_wps_er_pin_t;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t mac[6]; /**< MAC address of the station connected to ESP32 soft-AP */
|
|
||||||
uint8_t aid; /**< the aid that ESP32 soft-AP gives to the station connected to */
|
|
||||||
} system_event_ap_staconnected_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t mac[6]; /**< MAC address of the station disconnects to ESP32 soft-AP */
|
|
||||||
uint8_t aid; /**< the aid that ESP32 soft-AP gave to the station disconnects to */
|
|
||||||
} system_event_ap_stadisconnected_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int rssi; /**< Received probe request signal strength */
|
|
||||||
uint8_t mac[6]; /**< MAC address of the station which send probe request */
|
|
||||||
} system_event_ap_probe_req_rx_t;
|
|
||||||
|
|
||||||
|
/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
||||||
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
||||||
WPS_FAIL_REASON_MAX
|
WPS_FAIL_REASON_MAX
|
||||||
} system_event_sta_wps_fail_reason_t;
|
} wifi_event_sta_wps_fail_reason_t;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
system_event_sta_connected_t connected; /**< ESP32 station connected to AP */
|
wifi_event_sta_scan_done_t wifi_scan_done;
|
||||||
system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */
|
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
|
||||||
system_event_sta_scan_done_t scan_done; /**< ESP32 station scan (APs) done */
|
wifi_event_sta_connected_t wifi_sta_connected;
|
||||||
system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP32 station connected to changed */
|
wifi_event_sta_disconnected_t wifi_sta_disconnected;
|
||||||
system_event_sta_wps_fail_reason_t sta_er_fail_reason; /**< ESP32 station WPS enrollee mode failed reason code received */
|
} arduino_event_info_t;
|
||||||
system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */
|
|
||||||
system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */
|
|
||||||
system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */
|
|
||||||
} system_event_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
system_event_id_t event_id; /**< event ID */
|
arduino_event_id_t event_id; /**< event ID */
|
||||||
system_event_info_t event_info; /**< event information */
|
arduino_event_info_t event_info; /**< event information */
|
||||||
} system_event_t;
|
} arduino_event_t;
|
||||||
|
|
||||||
#define WiFiEvent_t system_event_id_t
|
#define WiFiEvent_t arduino_event_id_t
|
||||||
#define WiFiEventInfo_t system_event_info_t
|
#define WiFiEventInfo_t arduino_event_info_t
|
||||||
#define WiFiEventId_t wifi_event_id_t
|
#define WiFiEventId_t wifi_event_id_t
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -141,20 +128,20 @@ typedef enum {
|
|||||||
WL_DISCONNECTED = 6
|
WL_DISCONNECTED = 6
|
||||||
} wl_status_t;
|
} wl_status_t;
|
||||||
|
|
||||||
typedef void (*WiFiEventCb)(system_event_id_t event);
|
typedef void (*WiFiEventCb)(arduino_event_id_t event);
|
||||||
typedef std::function<void(system_event_id_t event, system_event_info_t info)> WiFiEventFuncCb;
|
typedef std::function<void(arduino_event_id_t event, arduino_event_info_t info)> WiFiEventFuncCb;
|
||||||
typedef void (*WiFiEventSysCb)(system_event_t * event);
|
typedef void (*WiFiEventSysCb)(arduino_event_t * event);
|
||||||
typedef size_t wifi_event_id_t;
|
typedef size_t wifi_event_id_t;
|
||||||
|
|
||||||
class WiFiClass {
|
class WiFiClass {
|
||||||
public:
|
public:
|
||||||
wifi_event_id_t onEvent(WiFiEventCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX) {
|
wifi_event_id_t onEvent(WiFiEventCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX) {
|
wifi_event_id_t onEvent(WiFiEventFuncCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
wifi_event_id_t onEvent(WiFiEventSysCb cbEvent, system_event_id_t event = SYSTEM_EVENT_MAX) {
|
wifi_event_id_t onEvent(WiFiEventSysCb cbEvent, arduino_event_id_t event = ARDUINO_EVENT_MAX) {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FS_BUFFER_SIZE
|
#ifndef FS_BUFFER_SIZE
|
||||||
#define FS_BUFFER_SIZE 4096
|
#define FS_BUFFER_SIZE 8192
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum class StateUpdateResult {
|
enum class StateUpdateResult {
|
||||||
|
|||||||
@@ -1,40 +1,5 @@
|
|||||||
(<https://github.com/emsesp/EMS-ESP32/issues/41>)
|
(Based on <https://github.com/emsesp/EMS-ESP32/issues/41>)
|
||||||
|
|
||||||
When developing and testing the web interface, it's handy not to bother with re-flashing an ESP32 each time. The idea is to mimic the ESP using a mock/stub server that responds to the REST (HTTP POST & GET) and WebSocket calls.
|
When developing and testing the web interface, it's handy not to bother with re-flashing an ESP32 each time. The idea is to mimic the ESP using a mock/stub server that responds to the REST (HTTP POST & GET) and WebSocket calls.
|
||||||
|
|
||||||
To set it up it do
|
To set it up it do run `npm install` in the `mock-api` folder, then from the `interface` folder run `npm run standalone`. This will start the mock API server on port 3080 using data from `mock-api/server.js` and the web server runs on port 3000.
|
||||||
|
|
||||||
```sh
|
|
||||||
% cd mock-api
|
|
||||||
% npm install
|
|
||||||
% cd interface
|
|
||||||
% npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
and to run it
|
|
||||||
|
|
||||||
```sh
|
|
||||||
% cd interface
|
|
||||||
% npm run standalone
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- new file `interface/src/setupProxy.js`
|
|
||||||
- new files `mock-api/server.js` with the hardcoded data. Requires its own npm packages for express
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
```bash
|
|
||||||
% curl -i http://localhost:3080/rest/emsespSettings
|
|
||||||
```
|
|
||||||
|
|
||||||
or from a browser use port 3000 since `setupProxy.js` is redirecting, like http://172.22.227.82:3000/rest/emsespSettings
|
|
||||||
|
|
||||||
http://172.22.227.82:3090/es/log?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWUsInZlcnNpb24iOiIzLjAuMmIwIn0.MsHSgoJKI1lyYz77EiT5ZN3ECMrb4mPv9FNy3udq0TU
|
|
||||||
|
|
||||||
Testing the EventSource/SSE use http://172.22.227.82:3090/es/log
|
|
||||||
|
|
||||||
## To Do
|
|
||||||
|
|
||||||
- add filter rule to prevent from exposing yourself to malicious attacks when running the dev server(<https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a>)
|
|
||||||
|
|||||||
1772
mock-api/package-lock.json
generated
1772
mock-api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,11 +11,11 @@
|
|||||||
"author": "proddy",
|
"author": "proddy",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@msgpack/msgpack": "^2.7.2",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"express-sse": "^0.5.3",
|
"express-sse": "^0.5.3",
|
||||||
"nodemon": "^2.0.16",
|
"nodemon": "^2.0.20",
|
||||||
"ws": "^8.7.0"
|
"ws": "^8.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,7 +314,6 @@ settings = {
|
|||||||
syslog_mark_interval: 0,
|
syslog_mark_interval: 0,
|
||||||
syslog_host: '192.168.1.4',
|
syslog_host: '192.168.1.4',
|
||||||
syslog_port: 514,
|
syslog_port: 514,
|
||||||
master_thermostat: 0,
|
|
||||||
shower_timer: true,
|
shower_timer: true,
|
||||||
shower_alert: true,
|
shower_alert: true,
|
||||||
shower_alert_trigger: 7,
|
shower_alert_trigger: 7,
|
||||||
@@ -348,18 +347,21 @@ const emsesp_devices = {
|
|||||||
d: 23,
|
d: 23,
|
||||||
p: 77,
|
p: 77,
|
||||||
s: 'Thermostat (RC20/Moduline 300)',
|
s: 'Thermostat (RC20/Moduline 300)',
|
||||||
|
t: 'thermostat1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i: 2,
|
i: 2,
|
||||||
d: 8,
|
d: 8,
|
||||||
p: 123,
|
p: 123,
|
||||||
s: 'Boiler (Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i)',
|
s: 'Boiler (Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i)',
|
||||||
|
t: 'boiler',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
i: 4,
|
i: 4,
|
||||||
d: 16,
|
d: 16,
|
||||||
p: 165,
|
p: 165,
|
||||||
s: 'Thermostat (RC100/Moduline 1000/1010)',
|
s: 'Thermostat (RC100/Moduline 1000/1010)',
|
||||||
|
t: 'thermostat2',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -593,13 +595,13 @@ const emsesp_deviceentities_1 = [
|
|||||||
m: 0,
|
m: 0,
|
||||||
w: false,
|
w: false,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
v: 'test data',
|
// v: 'test data',
|
||||||
n: 'test',
|
// n: 'test',
|
||||||
id: 'test',
|
// id: 'test',
|
||||||
m: 0,
|
// m: 0,
|
||||||
w: false,
|
// w: false,
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
v: 'roomTemp',
|
v: 'roomTemp',
|
||||||
id: 'hc1/HA climate config creation',
|
id: 'hc1/HA climate config creation',
|
||||||
@@ -1133,7 +1135,7 @@ rest_server.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
|
|||||||
// EMS-ESP API specific
|
// EMS-ESP API specific
|
||||||
const emsesp_info = {
|
const emsesp_info = {
|
||||||
System: {
|
System: {
|
||||||
version: '3.x.x',
|
version: '3.4.2',
|
||||||
uptime: '001+06:40:34.018',
|
uptime: '001+06:40:34.018',
|
||||||
'uptime (seconds)': 110434,
|
'uptime (seconds)': 110434,
|
||||||
freemem: 131,
|
freemem: 131,
|
||||||
@@ -1225,9 +1227,8 @@ rest_server.get(GET_CUSTOMIZATIONS_ENDPOINT, (req, res) => {
|
|||||||
|
|
||||||
// start server
|
// start server
|
||||||
const expressServer = rest_server.listen(port, () =>
|
const expressServer = rest_server.listen(port, () =>
|
||||||
console.log(`Mock server for EMS-ESP is up and running at http://localhost:${port}`),
|
console.log(`EMS-ESP REST API server running on http://localhost:${port}/api`),
|
||||||
)
|
)
|
||||||
console.log(`EMS-ESP Rest API listening to http://localhost:${port}/api`)
|
|
||||||
|
|
||||||
// start websocket server
|
// start websocket server
|
||||||
const websocketServer = new WebSocket.Server({
|
const websocketServer = new WebSocket.Server({
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ build_flags =
|
|||||||
-D NO_GLOBAL_ARDUINOOTA
|
-D NO_GLOBAL_ARDUINOOTA
|
||||||
-D ARDUINOJSON_ENABLE_STD_STRING=1
|
-D ARDUINOJSON_ENABLE_STD_STRING=1
|
||||||
-D ARDUINOJSON_USE_DOUBLE=0
|
-D ARDUINOJSON_USE_DOUBLE=0
|
||||||
|
-D CONFIG_UART_ISR_IN_IRAM
|
||||||
|
|
||||||
unbuild_flags =
|
unbuild_flags =
|
||||||
${common.core_unbuild_flags}
|
${common.core_unbuild_flags}
|
||||||
@@ -51,7 +52,7 @@ check_flags =
|
|||||||
[env:ci]
|
[env:ci]
|
||||||
extra_scripts = scripts/rename_fw.py
|
extra_scripts = scripts/rename_fw.py
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
platform = espressif32@3.5.0
|
platform = espressif32
|
||||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||||
build_flags = ${common.build_flags}
|
build_flags = ${common.build_flags}
|
||||||
build_unflags = ${common.unbuild_flags}
|
build_unflags = ${common.unbuild_flags}
|
||||||
@@ -61,7 +62,7 @@ extra_scripts =
|
|||||||
pre:scripts/build_interface.py
|
pre:scripts/build_interface.py
|
||||||
scripts/rename_fw.py
|
scripts/rename_fw.py
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
platform = espressif32@3.5.0
|
platform = espressif32
|
||||||
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
board_build.partitions = esp32_partition_app1984k_spiffs64k.csv
|
||||||
build_flags = ${common.build_flags}
|
build_flags = ${common.build_flags}
|
||||||
build_unflags = ${common.unbuild_flags}
|
build_unflags = ${common.unbuild_flags}
|
||||||
|
|||||||
@@ -29,3 +29,15 @@ Authorization: Bearer {{token}}
|
|||||||
"entity" : "seltemp",
|
"entity" : "seltemp",
|
||||||
"value" : 21.0
|
"value" : 21.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
POST http://10.10.10.134/api
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWV9.2bHpWya2C7Q12WjNUBD6_7N3RCD7CMl-EGhyQVzFdDg
|
||||||
|
|
||||||
|
{
|
||||||
|
"device" : "boiler",
|
||||||
|
"entity" : "wwtapactivated",
|
||||||
|
"value" : "on"
|
||||||
|
}
|
||||||
@@ -403,12 +403,19 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
snprintf(str, sizeof(str), "{{value_json['%d'].value}}", sensor.gpio());
|
snprintf(str, sizeof(str), "{{value_json['%d'].value}}", sensor.gpio());
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "Analog Sensor %s", sensor.name().c_str());
|
snprintf(str, sizeof(str), "analog_sensor_%s", sensor.name().c_str());
|
||||||
|
config["object_id"] = str;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
||||||
config["name"] = str;
|
config["name"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio());
|
snprintf(str, sizeof(str), "analogsensor_%d", sensor.gpio());
|
||||||
config["uniq_id"] = str;
|
config["uniq_id"] = str;
|
||||||
|
|
||||||
|
if (sensor.uom() != DeviceValueUOM::NONE) {
|
||||||
|
config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom());
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
JsonObject dev = config.createNestedObject("dev");
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class AnalogSensor {
|
|||||||
|
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
void set_name(const std::string & name) {
|
void set_name(const std::string & name) {
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t gpio() const {
|
uint8_t gpio() const {
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the function baesed on type
|
// call the function based on type
|
||||||
if (cf->cmdfunction_json_) {
|
if (cf->cmdfunction_json_) {
|
||||||
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
return_code = ((cf->cmdfunction_json_)(value, id, output)) ? CommandRet::OK : CommandRet::ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,10 +227,6 @@ void EMSESPShell::add_console_commands() {
|
|||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||||
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
shell.printfln(F_(tx_mode_fmt), settings.tx_mode);
|
||||||
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
shell.printfln(F_(bus_id_fmt), settings.ems_bus_id);
|
||||||
char buffer[4];
|
|
||||||
shell.printfln(F_(master_thermostat_fmt),
|
|
||||||
settings.master_thermostat == 0 ? read_flash_string(F_(auto)).c_str()
|
|
||||||
: Helpers::hextoa(buffer, settings.master_thermostat));
|
|
||||||
shell.printfln(F_(board_profile_fmt), settings.board_profile.c_str());
|
shell.printfln(F_(board_profile_fmt), settings.board_profile.c_str());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -261,23 +257,6 @@ void EMSESPShell::add_console_commands() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
commands->add_command(ShellContext::MAIN,
|
|
||||||
CommandFlags::ADMIN,
|
|
||||||
flash_string_vector{F_(set), F_(master), F_(thermostat)},
|
|
||||||
flash_string_vector{F_(deviceid_mandatory)},
|
|
||||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
|
||||||
uint8_t value = Helpers::hextoint(arguments.front().c_str());
|
|
||||||
EMSESP::webSettingsService.update(
|
|
||||||
[&](WebSettings & settings) {
|
|
||||||
settings.master_thermostat = value;
|
|
||||||
EMSESP::actual_master_thermostat(value); // set the internal value too
|
|
||||||
char buffer[5];
|
|
||||||
shell.printfln(F_(master_thermostat_fmt), !value ? read_flash_string(F_(auto)).c_str() : Helpers::hextoa(buffer, value));
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
},
|
|
||||||
"local");
|
|
||||||
});
|
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
commands->add_command(ShellContext::MAIN,
|
commands->add_command(ShellContext::MAIN,
|
||||||
CommandFlags::USER,
|
CommandFlags::USER,
|
||||||
@@ -419,7 +398,7 @@ void EMSESPShell::add_console_commands() {
|
|||||||
shell.print(F("Available commands are: "));
|
shell.print(F("Available commands are: "));
|
||||||
Command::show(shell, device_type, false); // non-verbose mode
|
Command::show(shell, device_type, false); // non-verbose mode
|
||||||
} else if (return_code != CommandRet::OK) {
|
} else if (return_code != CommandRet::OK) {
|
||||||
shell.println(F("Bad syntax"));
|
shell.printfln(F("Bad syntax (error code %d)"), return_code);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
[&](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) -> std::vector<std::string> {
|
||||||
|
|||||||
@@ -497,7 +497,10 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
snprintf(str, sizeof(str), "{{value_json['%s'].temp}}", sensor.id().c_str());
|
snprintf(str, sizeof(str), "{{value_json['%s'].temp}}", sensor.id().c_str());
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "Temperature Sensor %s", sensor.name().c_str());
|
snprintf(str, sizeof(str), "temperature_sensor_%s", sensor.name().c_str());
|
||||||
|
config["object_id"] = str;
|
||||||
|
|
||||||
|
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
||||||
config["name"] = str;
|
config["name"] = str;
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "dallasensor_%s", sensor.id().c_str());
|
snprintf(str, sizeof(str), "dallasensor_%s", sensor.id().c_str());
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class DallasSensor {
|
|||||||
|
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
void set_name(const std::string & name) {
|
void set_name(const std::string & name) {
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool apply_customization();
|
bool apply_customization();
|
||||||
|
|||||||
@@ -52,10 +52,6 @@
|
|||||||
#define EMSESP_DEFAULT_TRACELOG_RAW false
|
#define EMSESP_DEFAULT_TRACELOG_RAW false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_MASTER_THERMOSTAT
|
|
||||||
#define EMSESP_DEFAULT_MASTER_THERMOSTAT 0 // not set
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_SHOWER_TIMER
|
#ifndef EMSESP_DEFAULT_SHOWER_TIMER
|
||||||
#define EMSESP_DEFAULT_SHOWER_TIMER false
|
#define EMSESP_DEFAULT_SHOWER_TIMER false
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,11 +42,12 @@
|
|||||||
{173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
{173, DeviceType::BOILER, F("Geo 5xx"), DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP},
|
||||||
{195, DeviceType::BOILER, F("Condens 5000i/Greenstar 8000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{195, DeviceType::BOILER, F("Condens 5000i/Greenstar 8000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{203, DeviceType::BOILER, F("Logamax U122/Cerapur"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
{206, DeviceType::BOILER, F("Ecomline Excellent"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{208, DeviceType::BOILER, F("Logamax Plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{208, DeviceType::BOILER, F("Logamax Plus/GB192/Condens GC9000"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{210, DeviceType::BOILER, F("Cascade MC400"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{210, DeviceType::BOILER, F("Cascade MC400"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{211, DeviceType::BOILER, F("EasyControl Adapter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{211, DeviceType::BOILER, F("EasyControl Adapter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
{228, DeviceType::BOILER, F("Alternative Heatsource"), DeviceFlags::EMS_DEVICE_FLAG_AM200},
|
||||||
{234, DeviceType::BOILER, F("Logamax Plus GB122/Condense 2300"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{234, DeviceType::BOILER, F("Logamax Plus GB122/Condense 2300"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{206, DeviceType::BOILER, F("Ecomline Excellent"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
|
||||||
|
|
||||||
// Controllers - 0x09 / 0x10 / 0x50
|
// Controllers - 0x09 / 0x10 / 0x50
|
||||||
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
{ 68, DeviceType::CONTROLLER, F("BC10/RFM20"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||||
@@ -111,6 +112,9 @@
|
|||||||
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
{191, DeviceType::THERMOSTAT, F("FR120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS | DeviceFlags::EMS_DEVICE_FLAG_JUNKERS_OLD}, // older model
|
||||||
{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
{192, DeviceType::THERMOSTAT, F("FW120"), DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||||
|
|
||||||
|
// Thermostat remote - 0x38
|
||||||
|
{200, DeviceType::THERMOSTAT, F("RC100H"), DeviceFlags::EMS_DEVICE_FLAG_RC100H},
|
||||||
|
|
||||||
// Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww)
|
// Solar Modules - 0x30 (for solar), 0x2A, 0x41 (for ww)
|
||||||
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
{ 73, DeviceType::SOLAR, F("SM10"), DeviceFlags::EMS_DEVICE_FLAG_SM10},
|
||||||
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
{101, DeviceType::SOLAR, F("ISM1"), DeviceFlags::EMS_DEVICE_FLAG_ISM},
|
||||||
@@ -128,11 +132,12 @@
|
|||||||
{161, DeviceType::MIXER, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
{161, DeviceType::MIXER, F("MM200"), DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
|
||||||
{204, DeviceType::MIXER, F("MP100"), DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool
|
{204, DeviceType::MIXER, F("MP100"), DeviceFlags::EMS_DEVICE_FLAG_MP}, // pool
|
||||||
|
|
||||||
// Heat Pumps - 0x38
|
// Heat Pumps - 0x38?
|
||||||
{200, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
|
||||||
{248, DeviceType::HEATPUMP, F("Hybrid Manager HM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
|
||||||
{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{252, DeviceType::HEATPUMP, F("HP Module"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
|
// Heat Pumps - 0x53
|
||||||
|
{248, DeviceType::HEATPUMP, F("Hybrid Manager HM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Connect devices - 0x02
|
// Connect devices - 0x02
|
||||||
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{171, DeviceType::CONNECT, F("OpenTherm Converter"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{205, DeviceType::CONNECT, F("Moduline Easy Connect"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
@@ -145,6 +150,9 @@
|
|||||||
// Switches - 0x11
|
// Switches - 0x11
|
||||||
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{ 71, DeviceType::SWITCH, F("WM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
|
// EM10 error contact and analog flowtemp control- 0x12
|
||||||
|
{ 74, DeviceType::GATEWAY, F("Error Module EM10"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Gateways - 0x48
|
// Gateways - 0x48
|
||||||
{189, DeviceType::GATEWAY, F("KM200/MB LAN 2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{189, DeviceType::GATEWAY, F("KM200/MB LAN 2"), DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -131,7 +131,7 @@ class Boiler : public EMSdevice {
|
|||||||
uint32_t burn2WorkMin_; // burner stage 2 operating time
|
uint32_t burn2WorkMin_; // burner stage 2 operating time
|
||||||
uint32_t heatWorkMin_; // Total heat operating time
|
uint32_t heatWorkMin_; // Total heat operating time
|
||||||
uint32_t UBAuptime_; // Total UBA working hours
|
uint32_t UBAuptime_; // Total UBA working hours
|
||||||
char lastCode_[50]; // last error code
|
char lastCode_[55]; // last error code
|
||||||
char serviceCode_[4]; // 3 character status/service code
|
char serviceCode_[4]; // 3 character status/service code
|
||||||
uint16_t serviceCodeNumber_; // error/service code
|
uint16_t serviceCodeNumber_; // error/service code
|
||||||
uint8_t emergencyOps_;
|
uint8_t emergencyOps_;
|
||||||
@@ -198,6 +198,38 @@ class Boiler : public EMSdevice {
|
|||||||
// Pool unit
|
// Pool unit
|
||||||
int8_t poolSetTemp_;
|
int8_t poolSetTemp_;
|
||||||
|
|
||||||
|
// Alternative Heatsource AM200
|
||||||
|
int16_t cylTopTemp_; // TB1
|
||||||
|
int16_t cylCenterTemp_; // TB2
|
||||||
|
int16_t cylBottomTemp_; // TB3
|
||||||
|
int16_t aFlowTemp_; // TA1
|
||||||
|
int16_t aRetTemp_; // TR1
|
||||||
|
uint8_t aPumpMod_; // PR1 - percent
|
||||||
|
// uint8_t valveByPass_; // VR2
|
||||||
|
uint8_t valveBuffer_; // VB1
|
||||||
|
uint8_t valveReturn_; // VR1
|
||||||
|
// uint8_t heatSource_; // OEV
|
||||||
|
// Settings:
|
||||||
|
uint8_t vr2Config_; // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
|
||||||
|
uint8_t ahsActivated_; // pos 00: Alternate heat source activation: No(00),Yes(01)
|
||||||
|
uint8_t aPumpConfig_; // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
|
||||||
|
uint8_t aPumpSignal_; // pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
|
||||||
|
uint8_t aPumpMin_; // pos 21: Min output pump PR1 (%)
|
||||||
|
uint8_t tempRise_; // pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
|
||||||
|
uint8_t setReturnTemp_; // pos 06: Set temp return (°C) (VR1)
|
||||||
|
uint16_t mixRuntime_; // pos 10/11?: Mixer run time (s) (VR1)
|
||||||
|
// uint8_t setFlowTemp_; // pos 07: Set flow temp AHS (°C) (Buffer)
|
||||||
|
uint8_t bufBypass_; // pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
|
||||||
|
uint16_t bufMixRuntime_; // pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
|
||||||
|
uint8_t bufConfig_; // pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
|
||||||
|
uint8_t blockMode_; // pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
|
||||||
|
uint8_t blockTerm_; // pos 17: Config of block terminal: NO(00), NC(01)
|
||||||
|
int8_t blockHyst_; // pos 14?: Hyst. for bolier block (K)
|
||||||
|
uint8_t releaseWait_; // pos 15: Boiler release wait time (min)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
|
* Hybrid heatpump with telegram 0xBB is readable and writeable in boiler and thermostat
|
||||||
* thermostat always overwrites settings in boiler
|
* thermostat always overwrites settings in boiler
|
||||||
@@ -242,10 +274,14 @@ class Boiler : public EMSdevice {
|
|||||||
void process_HpOutdoor(std::shared_ptr<const Telegram> telegram);
|
void process_HpOutdoor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HpPool(std::shared_ptr<const Telegram> telegram);
|
void process_HpPool(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HybridHp(std::shared_ptr<const Telegram> telegram);
|
void process_HybridHp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_amTempMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_amStatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_amSettingMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_amCommandMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_amExtraMessage(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
// commands - none of these use the additional id parameter
|
// commands - none of these use the additional id parameter
|
||||||
bool set_ww_mode(const char * value, const int8_t id);
|
bool set_ww_mode(const char * value, const int8_t id);
|
||||||
bool set_ww_mode1(const char * value, const int8_t id);
|
|
||||||
bool set_ww_activated(const char * value, const int8_t id);
|
bool set_ww_activated(const char * value, const int8_t id);
|
||||||
bool set_tapwarmwater_activated(const char * value, const int8_t id);
|
bool set_tapwarmwater_activated(const char * value, const int8_t id);
|
||||||
bool set_ww_onetime(const char * value, const int8_t id);
|
bool set_ww_onetime(const char * value, const int8_t id);
|
||||||
@@ -282,6 +318,24 @@ class Boiler : public EMSdevice {
|
|||||||
bool set_pool_temp(const char * value, const int8_t id);
|
bool set_pool_temp(const char * value, const int8_t id);
|
||||||
bool set_emergency_temp(const char * value, const int8_t id);
|
bool set_emergency_temp(const char * value, const int8_t id);
|
||||||
bool set_emergency_ops(const char * value, const int8_t id);
|
bool set_emergency_ops(const char * value, const int8_t id);
|
||||||
|
|
||||||
|
bool set_vr2Config(const char * value, const int8_t id); // pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)
|
||||||
|
bool set_ahsActivated(const char * value, const int8_t id); // pos 00: Alternate heat source activation: No(00),Yes(01)
|
||||||
|
bool set_aPumpConfig(const char * value, const int8_t id); // pos 04: Buffer primary pump->Config pump: No(00),Yes(01)
|
||||||
|
bool set_aPumpSignal(const char * value, const int8_t id); // pos 03: Output for PR1 pump: On/Off(00),PWM(01),PWM invers(02)
|
||||||
|
bool set_aPumpMin(const char * value, const int8_t id); // pos 21: Min output pump PR1 (%)
|
||||||
|
bool set_tempRise(const char * value, const int8_t id); // pos 01: AHS return temp rise: No(00),Yes(01) (mixer VR1)
|
||||||
|
bool set_setReturnTemp(const char * value, const int8_t id); // pos 06: Set temp return (°C) (VR1)
|
||||||
|
bool set_mixRuntime(const char * value, const int8_t id); // pos 10/11?: Mixer run time (s) (VR1)
|
||||||
|
bool set_setFlowTemp(const char * value, const int8_t id); // pos 07: Set flow temp AHS (°C) (Buffer)
|
||||||
|
bool set_bufBypass(const char * value, const int8_t id); // pos 02: Puffer bypass: No(00), Mischer(01), Ventil(02) (Buffer)
|
||||||
|
bool set_bufMixRuntime(const char * value, const int8_t id); // pos 8/9: Bypass mixer run time: [time] (s) (Buffer)
|
||||||
|
bool set_bufConfig(const char * value, const int8_t id); // pos 20: Konfig WW-Speicher Monovalent(01), Bivalent(02) (buffer)
|
||||||
|
bool set_blockMode(const char * value, const int8_t id); // pos 16: Config htg. blocking mode: No(00),Automatic(01),Always block02) (blocking)
|
||||||
|
bool set_blockTerm(const char * value, const int8_t id); // pos 17: Config of block terminal: NO(00), NC(01)
|
||||||
|
bool set_blockHyst(const char * value, const int8_t id); // pos 14?: Hyst. for bolier block (K)
|
||||||
|
bool set_releaseWait(const char * value, const int8_t id); // pos 15: Boiler release wait time (min)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bool set_hybridStrategy(const char * value, const int8_t id);
|
bool set_hybridStrategy(const char * value, const int8_t id);
|
||||||
bool set_switchOverTemp(const char * value, const int8_t id);
|
bool set_switchOverTemp(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Controller::Controller(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
|
// IVT broadcasts Thermostat time from controller (0x09) if display is off.
|
||||||
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
|
if ((flags & 0x0F) == EMS_DEVICE_FLAG_IVT) {
|
||||||
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
|
register_telegram_type(0x06, F("RCTime"), false, MAKE_PF_CB(process_dateTime));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dateTime_, DeviceValueType::STRING, nullptr, FL_(dateTime), DeviceValueUOM::NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ void Controller::process_dateTime(std::shared_ptr<const Telegram> telegram) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char newdatetime[sizeof(dateTime_)];
|
char newdatetime[sizeof(dateTime_)];
|
||||||
// publish as dd.mm.yyyy hh:mmF
|
// publish as dd.mm.yyyy hh:mm
|
||||||
snprintf(newdatetime,
|
snprintf(newdatetime,
|
||||||
sizeof(dateTime_),
|
sizeof(dateTime_),
|
||||||
"%02d.%02d.%04d %02d:%02d",
|
"%02d.%02d.%04d %02d:%02d",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ Generic::Generic(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
|||||||
// RF-Sensor 0x40 sending temperature in telegram 0x435, see https://github.com/emsesp/EMS-ESP32/issues/103
|
// RF-Sensor 0x40 sending temperature in telegram 0x435, see https://github.com/emsesp/EMS-ESP32/issues/103
|
||||||
if (device_id == 0x40) {
|
if (device_id == 0x40) {
|
||||||
register_telegram_type(0x435, F("RFSensorMessage"), false, MAKE_PF_CB(process_RFSensorMessage));
|
register_telegram_type(0x435, F("RFSensorMessage"), false, MAKE_PF_CB(process_RFSensorMessage));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &rfTemp_, DeviceValueType::SHORT, FL_(div10), FL_(RFTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &rfTemp_, DeviceValueType::SHORT, FL_(div10), FL_(RFTemp), DeviceValueUOM::DEGREES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ REGISTER_FACTORY(Heatpump, EMSdevice::DeviceType::HEATPUMP);
|
|||||||
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
// telegram handlers
|
// telegram handlers
|
||||||
register_telegram_type(0x042B, F("HP1"), true, MAKE_PF_CB(process_HPMonitor1));
|
register_telegram_type(0x042B, F("HP1"), false, MAKE_PF_CB(process_HPMonitor1));
|
||||||
register_telegram_type(0x047B, F("HP2"), true, MAKE_PF_CB(process_HPMonitor2));
|
register_telegram_type(0x047B, F("HP2"), false, MAKE_PF_CB(process_HPMonitor2));
|
||||||
|
|
||||||
// device values
|
// device values
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &airHumidity_, DeviceValueType::UINT, FL_(div2), FL_(airHumidity), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, nullptr, FL_(airHumidity), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dewTemperature_, DeviceValueType::UINT, nullptr, FL_(dewTemperature), DeviceValueUOM::DEGREES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_MP) {
|
||||||
register_telegram_type(0x5BA, F("HpPoolStatus"), true, MAKE_PF_CB(process_HpPoolStatus));
|
register_telegram_type(0x5BA, F("HpPoolStatus"), true, MAKE_PF_CB(process_HpPoolStatus));
|
||||||
type_ = Type::MP;
|
type_ = Type::MP;
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &poolTemp_, DeviceValueType::SHORT, FL_(div10), FL_(poolTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolTemp_, DeviceValueType::SHORT, FL_(div10), FL_(poolTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShuntStatus_, DeviceValueType::ENUM, FL_(enum_shunt), FL_(poolShuntStatus), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &poolShunt_, DeviceValueType::UINT, nullptr, FL_(poolShunt), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &poolShunt_, DeviceValueType::UINT, nullptr, FL_(poolShunt), DeviceValueUOM::PERCENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMS+
|
// EMS+
|
||||||
|
|||||||
@@ -134,37 +134,43 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// common solar values for all modules (except dhw)
|
// common solar values for all modules (except dhw)
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorTemp_, DeviceValueType::SHORT, FL_(div10), FL_(collectorTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylBottomTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylBottomTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylBottomTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylBottomTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPump_, DeviceValueType::BOOL, nullptr, FL_(solarPump), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &pumpWorkTime_, DeviceValueType::TIME, nullptr, FL_(pumpWorkTime), DeviceValueUOM::MINUTES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &pumpWorkTime_, DeviceValueType::TIME, nullptr, FL_(pumpWorkTime), DeviceValueUOM::MINUTES);
|
||||||
register_device_value(
|
register_device_value(
|
||||||
DeviceValueTAG::TAG_NONE, &cylMaxTemp_, DeviceValueType::UINT, nullptr, FL_(cylMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_cylMaxTemp));
|
DeviceValueTAG::TAG_DEVICE_DATA, &cylMaxTemp_, DeviceValueType::UINT, nullptr, FL_(cylMaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_cylMaxTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
||||||
|
|
||||||
// values per device flag
|
// values per device flag
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM10) {
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
DeviceValueTAG::TAG_NONE, &solarPumpMinMod_, DeviceValueType::UINT, nullptr, FL_(pumpMinMod), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_PumpMinMod));
|
&solarPumpMinMod_,
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
DeviceValueType::UINT,
|
||||||
|
nullptr,
|
||||||
|
FL_(pumpMinMod),
|
||||||
|
DeviceValueUOM::PERCENT,
|
||||||
|
MAKE_CF_CB(set_PumpMinMod));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpTurnonDiff_,
|
&solarPumpTurnonDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(solarPumpTurnonDiff),
|
FL_(solarPumpTurnonDiff),
|
||||||
DeviceValueUOM::DEGREES_R,
|
DeviceValueUOM::DEGREES_R,
|
||||||
MAKE_CF_CB(set_TurnonDiff));
|
MAKE_CF_CB(set_TurnonDiff));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpTurnoffDiff_,
|
&solarPumpTurnoffDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(solarPumpTurnoffDiff),
|
FL_(solarPumpTurnoffDiff),
|
||||||
DeviceValueUOM::DEGREES_R,
|
DeviceValueUOM::DEGREES_R,
|
||||||
MAKE_CF_CB(set_TurnoffDiff));
|
MAKE_CF_CB(set_TurnoffDiff));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPower_, DeviceValueType::SHORT, nullptr, FL_(solarPower), DeviceValueUOM::W);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPower_, DeviceValueType::SHORT, nullptr, FL_(solarPower), DeviceValueUOM::W);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &maxFlow_, DeviceValueType::UINT, FL_(div10), FL_(maxFlow), DeviceValueUOM::LMIN, MAKE_CF_CB(set_SM10MaxFlow));
|
register_device_value(
|
||||||
|
DeviceValueTAG::TAG_DEVICE_DATA, &maxFlow_, DeviceValueType::UINT, FL_(div10), FL_(maxFlow), DeviceValueUOM::LMIN, MAKE_CF_CB(set_SM10MaxFlow));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA_WW,
|
||||||
&wwMinTemp_,
|
&wwMinTemp_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
@@ -172,7 +178,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
FL_(wwMinTemp),
|
FL_(wwMinTemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_wwMinTemp));
|
MAKE_CF_CB(set_wwMinTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarIsEnabled_,
|
&solarIsEnabled_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -182,102 +188,122 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
|
|
||||||
/* unknown values for testing and logging. Used by MichaelDvP
|
/* unknown values for testing and logging. Used by MichaelDvP
|
||||||
register_device_value(
|
register_device_value(
|
||||||
DeviceValueTAG::TAG_NONE, &setting3_, DeviceValueType::UINT, nullptr, FL_(setting3), DeviceValueUOM::NONE, MAKE_CF_CB(set_CollectorMaxTemp));
|
DeviceValueTAG::TAG_DEVICE_DATA, &setting3_, DeviceValueType::UINT, nullptr, FL_(setting3), DeviceValueUOM::NONE, MAKE_CF_CB(set_CollectorMaxTemp));
|
||||||
register_device_value(
|
register_device_value(
|
||||||
DeviceValueTAG::TAG_NONE, &setting4_, DeviceValueType::UINT, nullptr, FL_(setting4), DeviceValueUOM::NONE, MAKE_CF_CB(set_CollectorMinTemp));
|
DeviceValueTAG::TAG_DEVICE_DATA, &setting4_, DeviceValueType::UINT, nullptr, FL_(setting4), DeviceValueUOM::NONE, MAKE_CF_CB(set_CollectorMinTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &data11_, DeviceValueType::UINT, nullptr, FL_(data11), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &data11_, DeviceValueType::UINT, nullptr, FL_(data11), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &data12_, DeviceValueType::UINT, nullptr, FL_(data12), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &data12_, DeviceValueType::UINT, nullptr, FL_(data12), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &data1_, DeviceValueType::UINT, nullptr, FL_(data1), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &data1_, DeviceValueType::UINT, nullptr, FL_(data1), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &data0_, DeviceValueType::UINT, nullptr, FL_(data0), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &data0_, DeviceValueType::UINT, nullptr, FL_(data0), DeviceValueUOM::NONE);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_ISM) {
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylMiddleTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylMiddleTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylMiddleTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylMiddleTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &retHeatAssist_, DeviceValueType::SHORT, FL_(div10), FL_(retHeatAssist), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &retHeatAssist_, DeviceValueType::SHORT, FL_(div10), FL_(retHeatAssist), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &m1Valve_, DeviceValueType::BOOL, nullptr, FL_(m1Valve), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &m1Valve_, DeviceValueType::BOOL, nullptr, FL_(m1Valve), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
if (flags == EMSdevice::EMS_DEVICE_FLAG_SM100) {
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPumpMod_, DeviceValueType::UINT, nullptr, FL_(solarPumpMod), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpMinMod_,
|
&solarPumpMinMod_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
FL_(mul5),
|
FL_(mul5),
|
||||||
FL_(pumpMinMod),
|
FL_(pumpMinMod),
|
||||||
DeviceValueUOM::PERCENT,
|
DeviceValueUOM::PERCENT,
|
||||||
MAKE_CF_CB(set_PumpMinMod));
|
MAKE_CF_CB(set_PumpMinMod));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpTurnonDiff_,
|
&solarPumpTurnonDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
FL_(solarPumpTurnonDiff),
|
FL_(solarPumpTurnonDiff),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_TurnonDiff));
|
MAKE_CF_CB(set_TurnonDiff));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpTurnoffDiff_,
|
&solarPumpTurnoffDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
FL_(solarPumpTurnoffDiff),
|
FL_(solarPumpTurnoffDiff),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_TurnoffDiff));
|
MAKE_CF_CB(set_TurnoffDiff));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &collector2Temp_, DeviceValueType::SHORT, FL_(div10), FL_(collector2Temp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collector2Temp_, DeviceValueType::SHORT, FL_(div10), FL_(collector2Temp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylMiddleTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylMiddleTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylMiddleTemp_, DeviceValueType::SHORT, FL_(div10), FL_(cylMiddleTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &retHeatAssist_, DeviceValueType::SHORT, FL_(div10), FL_(retHeatAssist), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &retHeatAssist_, DeviceValueType::SHORT, FL_(div10), FL_(retHeatAssist), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &m1Valve_, DeviceValueType::BOOL, nullptr, FL_(m1Valve), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &m1Valve_, DeviceValueType::BOOL, nullptr, FL_(m1Valve), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &m1Power_, DeviceValueType::UINT, nullptr, FL_(m1Power), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &m1Power_, DeviceValueType::UINT, nullptr, FL_(m1Power), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPump2_, DeviceValueType::BOOL, nullptr, FL_(solarPump2), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPump2_, DeviceValueType::BOOL, nullptr, FL_(solarPump2), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &solarPump2Mod_, DeviceValueType::UINT, nullptr, FL_(solarPump2Mod), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &solarPump2Mod_, DeviceValueType::UINT, nullptr, FL_(solarPump2Mod), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylBottomTemp2_, DeviceValueType::SHORT, FL_(div10), FL_(cyl2BottomTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylBottomTemp2_, DeviceValueType::SHORT, FL_(div10), FL_(cyl2BottomTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &heatExchangerTemp_, DeviceValueType::SHORT, FL_(div10), FL_(heatExchangerTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylPumpMod_, DeviceValueType::UINT, nullptr, FL_(cylPumpMod), DeviceValueUOM::PERCENT);
|
&heatExchangerTemp_,
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus), DeviceValueUOM::NONE);
|
DeviceValueType::SHORT,
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
FL_(div10),
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
FL_(heatExchangerTemp),
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylPumpMod_, DeviceValueType::UINT, nullptr, FL_(cylPumpMod), DeviceValueUOM::PERCENT);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &valveStatus_, DeviceValueType::BOOL, nullptr, FL_(valveStatus), DeviceValueUOM::NONE);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, nullptr, FL_(cylHeated), DeviceValueUOM::NONE);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, nullptr, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collectorMaxTemp_,
|
&collectorMaxTemp_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(collectorMaxTemp),
|
FL_(collectorMaxTemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_CollectorMaxTemp));
|
MAKE_CF_CB(set_CollectorMaxTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collectorMinTemp_,
|
&collectorMinTemp_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(collectorMinTemp),
|
FL_(collectorMinTemp),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_CollectorMinTemp));
|
MAKE_CF_CB(set_CollectorMinTemp));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyLastHour_, DeviceValueType::ULONG, FL_(div10), FL_(energyLastHour), DeviceValueUOM::WH);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &energyToday_, DeviceValueType::ULONG, nullptr, FL_(energyToday), DeviceValueUOM::WH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyToday_, DeviceValueType::ULONG, nullptr, FL_(energyToday), DeviceValueUOM::WH);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &energyTotal_, DeviceValueType::ULONG, FL_(div10), FL_(energyTotal), DeviceValueUOM::KWH);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &energyTotal_, DeviceValueType::ULONG, FL_(div10), FL_(energyTotal), DeviceValueUOM::KWH);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &pump2WorkTime_, DeviceValueType::TIME, nullptr, FL_(pump2WorkTime), DeviceValueUOM::MINUTES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &pump2WorkTime_, DeviceValueType::TIME, nullptr, FL_(pump2WorkTime), DeviceValueUOM::MINUTES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &m1WorkTime_, DeviceValueType::TIME, nullptr, FL_(m1WorkTime), DeviceValueUOM::MINUTES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &m1WorkTime_, DeviceValueType::TIME, nullptr, FL_(m1WorkTime), DeviceValueUOM::MINUTES);
|
||||||
// register_device_value(DeviceValueTAG::TAG_NONE, &cyl2MaxTemp_, DeviceValueType::UINT, nullptr, FL_(cyl2MaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_cyl2MaxTemp));
|
// register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cyl2MaxTemp_, DeviceValueType::UINT, nullptr, FL_(cyl2MaxTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_cyl2MaxTemp));
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&heatTransferSystem_,
|
&heatTransferSystem_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(heatTransferSystem),
|
FL_(heatTransferSystem),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_heatTransferSystem));
|
MAKE_CF_CB(set_heatTransferSystem));
|
||||||
register_device_value(
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
DeviceValueTAG::TAG_NONE, &externalCyl_, DeviceValueType::BOOL, nullptr, FL_(externalCyl), DeviceValueUOM::NONE, MAKE_CF_CB(set_externalCyl));
|
&externalCyl_,
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
DeviceValueType::BOOL,
|
||||||
|
nullptr,
|
||||||
|
FL_(externalCyl),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_externalCyl));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&thermalDisinfect_,
|
&thermalDisinfect_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(thermalDisinfect),
|
FL_(thermalDisinfect),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_thermalDisinfect));
|
MAKE_CF_CB(set_thermalDisinfect));
|
||||||
register_device_value(
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
DeviceValueTAG::TAG_NONE, &heatMetering_, DeviceValueType::BOOL, nullptr, FL_(heatMetering), DeviceValueUOM::NONE, MAKE_CF_CB(set_heatMetering));
|
&heatMetering_,
|
||||||
register_device_value(
|
DeviceValueType::BOOL,
|
||||||
DeviceValueTAG::TAG_NONE, &solarIsEnabled_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE, MAKE_CF_CB(set_solarEnabled));
|
nullptr,
|
||||||
|
FL_(heatMetering),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_heatMetering));
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&solarIsEnabled_,
|
||||||
|
DeviceValueType::BOOL,
|
||||||
|
nullptr,
|
||||||
|
FL_(activated),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_solarEnabled));
|
||||||
|
|
||||||
// telegram 0x035A
|
// telegram 0x035A
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpMode_,
|
&solarPumpMode_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_solarmode),
|
FL_(enum_solarmode),
|
||||||
@@ -285,7 +311,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_solarMode));
|
MAKE_CF_CB(set_solarMode));
|
||||||
register_device_value( // pump kick for vacuum collector, 00=off
|
register_device_value( // pump kick for vacuum collector, 00=off
|
||||||
DeviceValueTAG::TAG_NONE,
|
DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPumpKick_,
|
&solarPumpKick_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -293,7 +319,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_solarPumpKick));
|
MAKE_CF_CB(set_solarPumpKick));
|
||||||
register_device_value( // system does not use antifreeze, 00=off
|
register_device_value( // system does not use antifreeze, 00=off
|
||||||
DeviceValueTAG::TAG_NONE,
|
DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&plainWaterMode_,
|
&plainWaterMode_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -301,7 +327,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_plainWaterMode));
|
MAKE_CF_CB(set_plainWaterMode));
|
||||||
register_device_value( // double Match Flow, 00=off
|
register_device_value( // double Match Flow, 00=off
|
||||||
DeviceValueTAG::TAG_NONE,
|
DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&doubleMatchFlow_,
|
&doubleMatchFlow_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -309,21 +335,21 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_doubleMatchFlow));
|
MAKE_CF_CB(set_doubleMatchFlow));
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPump2MinMod_,
|
&solarPump2MinMod_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(pump2MinMod),
|
FL_(pump2MinMod),
|
||||||
DeviceValueUOM::PERCENT,
|
DeviceValueUOM::PERCENT,
|
||||||
MAKE_CF_CB(set_Pump2MinMod));
|
MAKE_CF_CB(set_Pump2MinMod));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPump2TurnonDiff_,
|
&solarPump2TurnonDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
FL_(solarPump2TurnonDiff),
|
FL_(solarPump2TurnonDiff),
|
||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_TurnonDiff2));
|
MAKE_CF_CB(set_TurnonDiff2));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPump2TurnoffDiff_,
|
&solarPump2TurnoffDiff_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
@@ -331,7 +357,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::DEGREES,
|
DeviceValueUOM::DEGREES,
|
||||||
MAKE_CF_CB(set_TurnoffDiff2));
|
MAKE_CF_CB(set_TurnoffDiff2));
|
||||||
register_device_value( // pump kick for vacuum collector, 00=off
|
register_device_value( // pump kick for vacuum collector, 00=off
|
||||||
DeviceValueTAG::TAG_NONE,
|
DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&solarPump2Kick_,
|
&solarPump2Kick_,
|
||||||
DeviceValueType::BOOL,
|
DeviceValueType::BOOL,
|
||||||
nullptr,
|
nullptr,
|
||||||
@@ -340,53 +366,53 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
MAKE_CF_CB(set_solarPump2Kick));
|
MAKE_CF_CB(set_solarPump2Kick));
|
||||||
|
|
||||||
// telegram 0x380
|
// telegram 0x380
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&climateZone_,
|
&climateZone_,
|
||||||
DeviceValueType::UINT,
|
DeviceValueType::UINT,
|
||||||
nullptr,
|
nullptr,
|
||||||
FL_(climateZone),
|
FL_(climateZone),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_climateZone)); // climate zone identifier
|
MAKE_CF_CB(set_climateZone)); // climate zone identifier
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collector1Area_,
|
&collector1Area_,
|
||||||
DeviceValueType::USHORT,
|
DeviceValueType::USHORT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
FL_(collector1Area),
|
FL_(collector1Area),
|
||||||
DeviceValueUOM::SQM,
|
DeviceValueUOM::SQM,
|
||||||
MAKE_CF_CB(set_collector1Area)); // Area of collector field 1
|
MAKE_CF_CB(set_collector1Area)); // Area of collector field 1
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collector1Type_,
|
&collector1Type_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_collectortype),
|
FL_(enum_collectortype),
|
||||||
FL_(collector1Type),
|
FL_(collector1Type),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_collector1Type)); // Type of collector field 1, 01=flat, 02=vacuum
|
MAKE_CF_CB(set_collector1Type)); // Type of collector field 1, 01=flat, 02=vacuum
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collector2Area_,
|
&collector2Area_,
|
||||||
DeviceValueType::USHORT,
|
DeviceValueType::USHORT,
|
||||||
FL_(div10),
|
FL_(div10),
|
||||||
FL_(collector2Area),
|
FL_(collector2Area),
|
||||||
DeviceValueUOM::SQM,
|
DeviceValueUOM::SQM,
|
||||||
MAKE_CF_CB(set_collector2Area)); // Area of collector field 2
|
MAKE_CF_CB(set_collector2Area)); // Area of collector field 2
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&collector2Type_,
|
&collector2Type_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_collectortype),
|
FL_(enum_collectortype),
|
||||||
FL_(collector2Type),
|
FL_(collector2Type),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_collector2Type)); // Type of collector field 2, 01=flat, 02=vacuum
|
MAKE_CF_CB(set_collector2Type)); // Type of collector field 2, 01=flat, 02=vacuum
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&cylPriority_,
|
&cylPriority_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
FL_(enum_cylprio),
|
FL_(enum_cylprio),
|
||||||
FL_(cylPriority),
|
FL_(cylPriority),
|
||||||
DeviceValueUOM::NONE,
|
DeviceValueUOM::NONE,
|
||||||
MAKE_CF_CB(set_cylPriority));
|
MAKE_CF_CB(set_cylPriority));
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &heatCntFlowTemp_, DeviceValueType::USHORT, FL_(div10), FL_(heatCntFlowTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatCntFlowTemp_, DeviceValueType::USHORT, FL_(div10), FL_(heatCntFlowTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &heatCntRetTemp_, DeviceValueType::USHORT, FL_(div10), FL_(heatCntRetTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatCntRetTemp_, DeviceValueType::USHORT, FL_(div10), FL_(heatCntRetTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &heatCnt_, DeviceValueType::UINT, nullptr, FL_(heatCnt), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatCnt_, DeviceValueType::UINT, nullptr, FL_(heatCnt), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &swapFlowTemp_, DeviceValueType::USHORT, FL_(div10), FL_(swapFlowTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &swapFlowTemp_, DeviceValueType::USHORT, FL_(div10), FL_(swapFlowTemp), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &swapRetTemp_, DeviceValueType::USHORT, FL_(div10), FL_(swapRetTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &swapRetTemp_, DeviceValueType::USHORT, FL_(div10), FL_(swapRetTemp), DeviceValueUOM::DEGREES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ REGISTER_FACTORY(Switch, EMSdevice::DeviceType::SWITCH);
|
|||||||
|
|
||||||
Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
Switch::Switch(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const std::string & name, uint8_t flags, uint8_t brand)
|
||||||
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
: EMSdevice(device_type, device_id, product_id, version, name, flags, brand) {
|
||||||
|
// WM10 module, device_id 0x11
|
||||||
register_telegram_type(0x9C, F("WM10MonitorMessage"), false, MAKE_PF_CB(process_WM10MonitorMessage));
|
register_telegram_type(0x9C, F("WM10MonitorMessage"), false, MAKE_PF_CB(process_WM10MonitorMessage));
|
||||||
register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage));
|
register_telegram_type(0x9D, F("WM10SetMessage"), false, MAKE_PF_CB(process_WM10SetMessage));
|
||||||
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
|
register_telegram_type(0x1E, F("WM10TempMessage"), false, MAKE_PF_CB(process_WM10TempMessage));
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &activated_, DeviceValueType::BOOL, nullptr, FL_(activated), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &flowTempHc_, DeviceValueType::USHORT, FL_(div10), FL_(flowTempHc), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_NONE, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &status_, DeviceValueType::INT, nullptr, FL_(status), DeviceValueUOM::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// message 0x9D switch on/off
|
// message 0x9D switch on/off
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@ class Thermostat : public EMSdevice {
|
|||||||
int16_t roomTemp;
|
int16_t roomTemp;
|
||||||
int16_t remotetemp; // for readback
|
int16_t remotetemp; // for readback
|
||||||
uint8_t tempautotemp;
|
uint8_t tempautotemp;
|
||||||
|
int8_t remoteseltemp;
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint8_t modetype;
|
uint8_t modetype;
|
||||||
uint8_t summermode;
|
uint8_t summermode;
|
||||||
@@ -56,6 +57,7 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t manualtemp;
|
uint8_t manualtemp;
|
||||||
uint8_t summersetmode;
|
uint8_t summersetmode;
|
||||||
uint8_t hpoperatingmode;
|
uint8_t hpoperatingmode;
|
||||||
|
uint8_t hpoperatingstate;
|
||||||
uint8_t roominfluence;
|
uint8_t roominfluence;
|
||||||
uint8_t roominfl_factor;
|
uint8_t roominfl_factor;
|
||||||
int16_t curroominfl;
|
int16_t curroominfl;
|
||||||
@@ -80,6 +82,8 @@ class Thermostat : public EMSdevice {
|
|||||||
char switchtime1[16];
|
char switchtime1[16];
|
||||||
char switchtime2[16];
|
char switchtime2[16];
|
||||||
uint8_t climate;
|
uint8_t climate;
|
||||||
|
uint8_t switchonoptimization;
|
||||||
|
uint8_t statusbyte; // from RC300monitor
|
||||||
|
|
||||||
// RC 10
|
// RC 10
|
||||||
uint8_t reducehours; // night reduce duration
|
uint8_t reducehours; // night reduce duration
|
||||||
@@ -130,6 +134,7 @@ class Thermostat : public EMSdevice {
|
|||||||
ON,
|
ON,
|
||||||
DAYLOW,
|
DAYLOW,
|
||||||
DAYMID,
|
DAYMID,
|
||||||
|
REMOTESELTEMP,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -160,6 +165,7 @@ class Thermostat : public EMSdevice {
|
|||||||
// each thermostat has a list of heating controller type IDs for reading and writing
|
// each thermostat has a list of heating controller type IDs for reading and writing
|
||||||
std::vector<uint16_t> monitor_typeids;
|
std::vector<uint16_t> monitor_typeids;
|
||||||
std::vector<uint16_t> set_typeids;
|
std::vector<uint16_t> set_typeids;
|
||||||
|
std::vector<uint16_t> set2_typeids;
|
||||||
std::vector<uint16_t> timer_typeids;
|
std::vector<uint16_t> timer_typeids;
|
||||||
std::vector<uint16_t> timer2_typeids;
|
std::vector<uint16_t> timer2_typeids;
|
||||||
std::vector<uint16_t> summer_typeids;
|
std::vector<uint16_t> summer_typeids;
|
||||||
@@ -189,12 +195,14 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
|
uint8_t offtemp_; // Set Temperature when mode is Off / 10 (e.g.: 0x0F = 7.5 degrees Celsius)
|
||||||
uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
|
uint8_t mixingvalves_; // Number of Mixing Valves: (0x00=0, 0x01=1, 0x02=2)
|
||||||
|
|
||||||
int8_t dampedoutdoortemp_;
|
int8_t dampedoutdoortemp_;
|
||||||
uint16_t tempsensor1_;
|
int16_t tempsensor1_;
|
||||||
uint16_t tempsensor2_;
|
int16_t tempsensor2_;
|
||||||
int16_t dampedoutdoortemp2_;
|
int16_t dampedoutdoortemp2_;
|
||||||
uint8_t floordrystatus_;
|
uint8_t floordrystatus_;
|
||||||
uint8_t floordrytemp_;
|
uint8_t floordrytemp_;
|
||||||
|
uint8_t dewtemperature_;
|
||||||
|
uint8_t humidity_;
|
||||||
|
|
||||||
uint8_t wwExtra1_; // wwExtra active for wwSystem 1
|
uint8_t wwExtra1_; // wwExtra active for wwSystem 1
|
||||||
uint8_t wwExtra2_;
|
uint8_t wwExtra2_;
|
||||||
@@ -217,6 +225,8 @@ class Thermostat : public EMSdevice {
|
|||||||
uint8_t wwDailyHeating_;
|
uint8_t wwDailyHeating_;
|
||||||
uint8_t wwDailyHeatTime_;
|
uint8_t wwDailyHeatTime_;
|
||||||
uint8_t wwWhenModeOff_;
|
uint8_t wwWhenModeOff_;
|
||||||
|
char wwHoliday_[26];
|
||||||
|
char wwVacation_[26];
|
||||||
|
|
||||||
// HybridHP
|
// HybridHP
|
||||||
uint8_t hybridStrategy_; // co2 = 1, cost = 2, temperature = 3, mix = 4
|
uint8_t hybridStrategy_; // co2 = 1, cost = 2, temperature = 3, mix = 4
|
||||||
@@ -357,6 +367,7 @@ class Thermostat : public EMSdevice {
|
|||||||
void process_CRFMonitor(std::shared_ptr<const Telegram> telegram);
|
void process_CRFMonitor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
|
void process_RC300Monitor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_RC300Set(std::shared_ptr<const Telegram> telegram);
|
void process_RC300Set(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_RC300Set2(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
|
void process_RC300Summer(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
|
void process_RC300Summer2(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
|
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
|
||||||
@@ -373,6 +384,9 @@ class Thermostat : public EMSdevice {
|
|||||||
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
|
void process_JunkersRemoteMonitor(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_JunkersHybridSettings(std::shared_ptr<const Telegram> telegram);
|
void process_JunkersHybridSettings(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram);
|
void process_JunkersSetMixer(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_RemoteTemp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_RemoteHumidity(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_RemoteCorrection(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
// internal helper functions
|
// internal helper functions
|
||||||
bool set_mode_n(const uint8_t mode, const uint8_t hc_num);
|
bool set_mode_n(const uint8_t mode, const uint8_t hc_num);
|
||||||
@@ -412,7 +426,6 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_vacreducetemp(const char * value, const int8_t id);
|
bool set_vacreducetemp(const char * value, const int8_t id);
|
||||||
bool set_vacreducemode(const char * value, const int8_t id);
|
bool set_vacreducemode(const char * value, const int8_t id);
|
||||||
bool set_nofrostmode(const char * value, const int8_t id);
|
bool set_nofrostmode(const char * value, const int8_t id);
|
||||||
|
|
||||||
bool set_remotetemp(const char * value, const int8_t id);
|
bool set_remotetemp(const char * value, const int8_t id);
|
||||||
bool set_roominfluence(const char * value, const int8_t id);
|
bool set_roominfluence(const char * value, const int8_t id);
|
||||||
bool set_roominfl_factor(const char * value, const int8_t id);
|
bool set_roominfl_factor(const char * value, const int8_t id);
|
||||||
@@ -426,6 +439,8 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_controlmode(const char * value, const int8_t id);
|
bool set_controlmode(const char * value, const int8_t id);
|
||||||
bool set_wwprio(const char * value, const int8_t id);
|
bool set_wwprio(const char * value, const int8_t id);
|
||||||
bool set_fastheatup(const char * value, const int8_t id);
|
bool set_fastheatup(const char * value, const int8_t id);
|
||||||
|
bool set_switchonoptimization(const char * value, const int8_t id);
|
||||||
|
bool set_remoteseltemp(const char * value, const int8_t id);
|
||||||
|
|
||||||
// set functions - these don't use the id/hc, the parameters are ignored
|
// set functions - these don't use the id/hc, the parameters are ignored
|
||||||
bool set_wwmode(const char * value, const int8_t id);
|
bool set_wwmode(const char * value, const int8_t id);
|
||||||
@@ -446,6 +461,12 @@ class Thermostat : public EMSdevice {
|
|||||||
bool set_wwDailyHeating(const char * value, const int8_t id);
|
bool set_wwDailyHeating(const char * value, const int8_t id);
|
||||||
bool set_wwDailyHeatTime(const char * value, const int8_t id);
|
bool set_wwDailyHeatTime(const char * value, const int8_t id);
|
||||||
bool set_wwwhenmodeoff(const char * value, const int8_t id);
|
bool set_wwwhenmodeoff(const char * value, const int8_t id);
|
||||||
|
bool set_wwVacation(const char * value, const int8_t id) {
|
||||||
|
return set_holiday(value, DeviceValueTAG::TAG_WWC1, true);
|
||||||
|
}
|
||||||
|
bool set_wwHoliday(const char * value, const int8_t id) {
|
||||||
|
return set_holiday(value, DeviceValueTAG::TAG_WWC1);
|
||||||
|
}
|
||||||
|
|
||||||
bool set_datetime(const char * value, const int8_t id);
|
bool set_datetime(const char * value, const int8_t id);
|
||||||
bool set_minexttemp(const char * value, const int8_t id);
|
bool set_minexttemp(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ std::string EMSdevice::device_type_2_device_name(const uint8_t device_type) {
|
|||||||
// returns device_type from a string
|
// returns device_type from a string
|
||||||
uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
|
uint8_t EMSdevice::device_name_2_device_type(const char * topic) {
|
||||||
if (!topic) {
|
if (!topic) {
|
||||||
return DeviceType::UNKNOWN; // nullptr
|
return DeviceType::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert topic to lowercase and compare
|
// convert topic to lowercase and compare
|
||||||
@@ -244,6 +244,16 @@ bool EMSdevice::is_fetch(uint16_t telegram_id) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for a tag to create a nest
|
||||||
|
bool EMSdevice::has_tag(const uint8_t tag) const {
|
||||||
|
for (const auto & dv : devicevalues_) {
|
||||||
|
if (dv.tag == tag && tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// list of registered device entries
|
// list of registered device entries
|
||||||
// called from the command 'entities'
|
// called from the command 'entities'
|
||||||
void EMSdevice::list_device_entries(JsonObject & output) const {
|
void EMSdevice::list_device_entries(JsonObject & output) const {
|
||||||
@@ -469,7 +479,7 @@ void EMSdevice::register_device_value(uint8_t tag,
|
|||||||
flags |= CommandFlag::MQTT_SUB_FLAG_HC;
|
flags |= CommandFlag::MQTT_SUB_FLAG_HC;
|
||||||
} else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) {
|
} else if (tag >= DeviceValueTAG::TAG_WWC1 && tag <= DeviceValueTAG::TAG_WWC10) {
|
||||||
flags |= CommandFlag::MQTT_SUB_FLAG_WWC;
|
flags |= CommandFlag::MQTT_SUB_FLAG_WWC;
|
||||||
} else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW) {
|
} else if (tag == DeviceValueTAG::TAG_DEVICE_DATA_WW || tag == DeviceValueTAG::TAG_BOILER_DATA_WW) {
|
||||||
flags |= CommandFlag::MQTT_SUB_FLAG_WW;
|
flags |= CommandFlag::MQTT_SUB_FLAG_WW;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +551,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
if (dv.value_p == value_p && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
if (dv.value_p == value_p && !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
if (Mqtt::publish_single2cmd()) {
|
if (Mqtt::publish_single2cmd()) {
|
||||||
if (dv.tag >= DeviceValueTAG::TAG_HC1 && dv.tag <= DeviceValueTAG::TAG_WWC10) {
|
if (dv.tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(topic,
|
snprintf(topic,
|
||||||
sizeof(topic),
|
sizeof(topic),
|
||||||
"%s/%s/%s",
|
"%s/%s/%s",
|
||||||
@@ -563,7 +573,7 @@ void EMSdevice::publish_value(void * value_p) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0;
|
int8_t divider = (dv.options_size == 1) ? Helpers::atoint(read_flash_string(dv.options[0]).c_str()) : 0;
|
||||||
char payload[50] = {'\0'};
|
char payload[55] = {'\0'};
|
||||||
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
|
||||||
|
|
||||||
switch (dv.type) {
|
switch (dv.type) {
|
||||||
@@ -900,11 +910,9 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
|
|||||||
JsonObject json = output;
|
JsonObject json = output;
|
||||||
int8_t tag = id;
|
int8_t tag = id;
|
||||||
|
|
||||||
// check if we have hc or wwc
|
// check if we have hc or wwc or hs
|
||||||
if (id >= 1 && id <= 8) {
|
if (id >= 1 && id <= (1 + DeviceValueTAG::TAG_HS16 - DeviceValueTAG::TAG_HC1)) {
|
||||||
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
||||||
} else if (id >= 9 && id <= 19) {
|
|
||||||
tag = DeviceValueTAG::TAG_WWC1 + id - 9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make a copy of the string command for parsing
|
// make a copy of the string command for parsing
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ class EMSdevice {
|
|||||||
static std::string tag_to_string(uint8_t tag);
|
static std::string tag_to_string(uint8_t tag);
|
||||||
static std::string tag_to_mqtt(uint8_t tag);
|
static std::string tag_to_mqtt(uint8_t tag);
|
||||||
|
|
||||||
|
bool has_tag(const uint8_t tag) const;
|
||||||
|
|
||||||
inline uint8_t device_id() const {
|
inline uint8_t device_id() const {
|
||||||
return device_id_;
|
return device_id_;
|
||||||
}
|
}
|
||||||
@@ -307,6 +309,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER = 0x08; // fixed device_id for Master Boiler/UBA
|
static constexpr uint8_t EMS_DEVICE_ID_BOILER = 0x08; // fixed device_id for Master Boiler/UBA
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_1 = 0x70; // fixed device_id for 1st. Cascade Boiler/UBA
|
static constexpr uint8_t EMS_DEVICE_ID_BOILER_1 = 0x70; // fixed device_id for 1st. Cascade Boiler/UBA
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_BOILER_F = 0x7F; // fixed device_id for last Cascade Boiler/UBA
|
static constexpr uint8_t EMS_DEVICE_ID_BOILER_F = 0x7F; // fixed device_id for last Cascade Boiler/UBA
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_AM200 = 0x60; // fixed device_id for alternative Heating AM200
|
||||||
|
|
||||||
// generic type IDs
|
// generic type IDs
|
||||||
static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices.
|
static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices.
|
||||||
@@ -324,6 +327,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HT3 = 3;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HEATPUMP = 4;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 5;
|
static constexpr uint8_t EMS_DEVICE_FLAG_HYBRID = 5;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_FLAG_AM200 = 6;
|
||||||
|
|
||||||
// Solar Module
|
// Solar Module
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
static constexpr uint8_t EMS_DEVICE_FLAG_SM10 = 1;
|
||||||
@@ -351,6 +355,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_FLAG_RC100 = 10;
|
static constexpr uint8_t EMS_DEVICE_FLAG_RC100 = 10;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_JUNKERS = 11;
|
static constexpr uint8_t EMS_DEVICE_FLAG_JUNKERS = 11;
|
||||||
static constexpr uint8_t EMS_DEVICE_FLAG_CRF = 12; // CRF200 only monitor
|
static constexpr uint8_t EMS_DEVICE_FLAG_CRF = 12; // CRF200 only monitor
|
||||||
|
static constexpr uint8_t EMS_DEVICE_FLAG_RC100H = 13; // with humidity
|
||||||
|
|
||||||
uint8_t count_entities();
|
uint8_t count_entities();
|
||||||
bool has_entities() const;
|
bool has_entities() const;
|
||||||
|
|||||||
@@ -53,45 +53,46 @@ const __FlashStringHelper * DeviceValue::DeviceValueUOM_s[] __attribute__((__ali
|
|||||||
// must be an int of 4 bytes, 32bit aligned
|
// must be an int of 4 bytes, 32bit aligned
|
||||||
const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = {
|
const __FlashStringHelper * const DeviceValue::DeviceValueTAG_s[] PROGMEM = {
|
||||||
|
|
||||||
F_(tag_none), // ""
|
F_(tag_none), // ""
|
||||||
F_(tag_heartbeat), // ""
|
F_(tag_heartbeat), // ""
|
||||||
F_(tag_boiler_data), // ""
|
F_(tag_boiler_data_ww), // "dhw"
|
||||||
F_(tag_device_data_ww), // "ww"
|
F_(tag_device_data), // ""
|
||||||
F_(tag_thermostat_data), // ""
|
F_(tag_device_data_ww), // "dhw"
|
||||||
F_(tag_hc1), // "hc1"
|
F_(tag_hc1), // "hc1"
|
||||||
F_(tag_hc2), // "hc2"
|
F_(tag_hc2), // "hc2"
|
||||||
F_(tag_hc3), // "hc3"
|
F_(tag_hc3), // "hc3"
|
||||||
F_(tag_hc4), // "hc4"
|
F_(tag_hc4), // "hc4"
|
||||||
F_(tag_hc5), // "hc5"
|
F_(tag_hc5), // "hc5"
|
||||||
F_(tag_hc6), // "hc6"
|
F_(tag_hc6), // "hc6"
|
||||||
F_(tag_hc7), // "hc7"
|
F_(tag_hc7), // "hc7"
|
||||||
F_(tag_hc8), // "hc8"
|
F_(tag_hc8), // "hc8"
|
||||||
F_(tag_wwc1), // "wwc1"
|
F_(tag_wwc1), // "wwc1"
|
||||||
F_(tag_wwc2), // "Wwc2"
|
F_(tag_wwc2), // "Wwc2"
|
||||||
F_(tag_wwc3), // "wwc3"
|
F_(tag_wwc3), // "wwc3"
|
||||||
F_(tag_wwc4), // "wwc4"
|
F_(tag_wwc4), // "wwc4"
|
||||||
F_(tag_wwc5), // "wwc5"
|
F_(tag_wwc5), // "wwc5"
|
||||||
F_(tag_wwc6), // "wwc6"
|
F_(tag_wwc6), // "wwc6"
|
||||||
F_(tag_wwc7), // "wwc7"
|
F_(tag_wwc7), // "wwc7"
|
||||||
F_(tag_wwc8), // "wwc8"
|
F_(tag_wwc8), // "wwc8"
|
||||||
F_(tag_wwc9), // "wwc9"
|
F_(tag_wwc9), // "wwc9"
|
||||||
F_(tag_wwc10), // "wwc10"
|
F_(tag_wwc10), // "wwc10"
|
||||||
F_(tag_hs1), // "hs1"
|
F_(tag_ahs), // "ahs"
|
||||||
F_(tag_hs2), // "hs2"
|
F_(tag_hs1), // "hs1"
|
||||||
F_(tag_hs3), // "hs3"
|
F_(tag_hs2), // "hs2"
|
||||||
F_(tag_hs4), // "hs4"
|
F_(tag_hs3), // "hs3"
|
||||||
F_(tag_hs5), // "hs5"
|
F_(tag_hs4), // "hs4"
|
||||||
F_(tag_hs6), // "hs6"
|
F_(tag_hs5), // "hs5"
|
||||||
F_(tag_hs7), // "hs7"
|
F_(tag_hs6), // "hs6"
|
||||||
F_(tag_hs8), // "hs8"
|
F_(tag_hs7), // "hs7"
|
||||||
F_(tag_hs9), // "hs9"
|
F_(tag_hs8), // "hs8"
|
||||||
F_(tag_hs10), // "hs10"
|
F_(tag_hs9), // "hs9"
|
||||||
F_(tag_hs11), // "hs11"
|
F_(tag_hs10), // "hs10"
|
||||||
F_(tag_hs12), // "hs12"
|
F_(tag_hs11), // "hs11"
|
||||||
F_(tag_hs13), // "hs13"
|
F_(tag_hs12), // "hs12"
|
||||||
F_(tag_hs14), // "hs14"
|
F_(tag_hs13), // "hs13"
|
||||||
F_(tag_hs15), // "hs15"
|
F_(tag_hs14), // "hs14"
|
||||||
F_(tag_hs16) // "hs16"
|
F_(tag_hs15), // "hs15"
|
||||||
|
F_(tag_hs16) // "hs16"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -100,9 +101,9 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = {
|
|||||||
|
|
||||||
F_(tag_none), // ""
|
F_(tag_none), // ""
|
||||||
F_(heartbeat), // "heartbeat"
|
F_(heartbeat), // "heartbeat"
|
||||||
F_(tag_boiler_data_mqtt), // ""
|
F_(tag_boiler_data_ww_mqtt), // "ww"
|
||||||
F_(tag_device_data_ww_mqtt), // "ww"
|
F_(tag_device_data), // ""
|
||||||
F_(tag_thermostat_data), // ""
|
F_(tag_device_data_ww_mqtt), // ""
|
||||||
F_(tag_hc1), // "hc1"
|
F_(tag_hc1), // "hc1"
|
||||||
F_(tag_hc2), // "hc2"
|
F_(tag_hc2), // "hc2"
|
||||||
F_(tag_hc3), // "hc3"
|
F_(tag_hc3), // "hc3"
|
||||||
@@ -121,6 +122,7 @@ const __FlashStringHelper * const DeviceValue::DeviceValueTAG_mqtt[] PROGMEM = {
|
|||||||
F_(tag_wwc8), // "wwc8"
|
F_(tag_wwc8), // "wwc8"
|
||||||
F_(tag_wwc9), // "wwc9"
|
F_(tag_wwc9), // "wwc9"
|
||||||
F_(tag_wwc10), // "wwc10"
|
F_(tag_wwc10), // "wwc10"
|
||||||
|
F_(tag_ahs), // "ahs"
|
||||||
F_(tag_hs1), // "hs1"
|
F_(tag_hs1), // "hs1"
|
||||||
F_(tag_hs2), // "hs2"
|
F_(tag_hs2), // "hs2"
|
||||||
F_(tag_hs3), // "hs3"
|
F_(tag_hs3), // "hs3"
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ class DeviceValue {
|
|||||||
enum DeviceValueTAG : uint8_t {
|
enum DeviceValueTAG : uint8_t {
|
||||||
TAG_NONE = 0, // wild card
|
TAG_NONE = 0, // wild card
|
||||||
TAG_HEARTBEAT,
|
TAG_HEARTBEAT,
|
||||||
TAG_BOILER_DATA,
|
TAG_BOILER_DATA_WW,
|
||||||
|
TAG_DEVICE_DATA,
|
||||||
TAG_DEVICE_DATA_WW,
|
TAG_DEVICE_DATA_WW,
|
||||||
TAG_THERMOSTAT_DATA,
|
|
||||||
TAG_HC1,
|
TAG_HC1,
|
||||||
TAG_HC2,
|
TAG_HC2,
|
||||||
TAG_HC3,
|
TAG_HC3,
|
||||||
@@ -96,6 +96,7 @@ class DeviceValue {
|
|||||||
TAG_WWC8,
|
TAG_WWC8,
|
||||||
TAG_WWC9,
|
TAG_WWC9,
|
||||||
TAG_WWC10,
|
TAG_WWC10,
|
||||||
|
TAG_AHS,
|
||||||
TAG_HS1,
|
TAG_HS1,
|
||||||
TAG_HS2,
|
TAG_HS2,
|
||||||
TAG_HS3,
|
TAG_HS3,
|
||||||
|
|||||||
268
src/emsesp.cpp
268
src/emsesp.cpp
@@ -28,9 +28,9 @@ ESP8266React EMSESP::esp8266React(&webServer, &dummyFS);
|
|||||||
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
#else
|
#else
|
||||||
ESP8266React EMSESP::esp8266React(&webServer, &LITTLEFS);
|
ESP8266React EMSESP::esp8266React(&webServer, &LittleFS);
|
||||||
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LITTLEFS, EMSESP::esp8266React.getSecurityManager());
|
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LITTLEFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager());
|
WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager());
|
||||||
@@ -60,19 +60,18 @@ AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
|||||||
Shower EMSESP::shower_; // Shower logic
|
Shower EMSESP::shower_; // Shower logic
|
||||||
|
|
||||||
// static/common variables
|
// static/common variables
|
||||||
uint8_t EMSESP::actual_master_thermostat_ = EMSESP_DEFAULT_MASTER_THERMOSTAT; // which thermostat leads when multiple found
|
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
|
uint8_t EMSESP::watch_ = 0; // trace off
|
||||||
uint8_t EMSESP::watch_ = 0; // trace off
|
uint16_t EMSESP::read_id_ = WATCH_ID_NONE;
|
||||||
uint16_t EMSESP::read_id_ = WATCH_ID_NONE;
|
bool EMSESP::read_next_ = false;
|
||||||
bool EMSESP::read_next_ = false;
|
uint16_t EMSESP::publish_id_ = 0;
|
||||||
uint16_t EMSESP::publish_id_ = 0;
|
bool EMSESP::tap_water_active_ = false; // for when Boiler states we having running warm water. used in Shower()
|
||||||
bool EMSESP::tap_water_active_ = false; // for when Boiler states we having running warm water. used in Shower()
|
uint32_t EMSESP::last_fetch_ = 0;
|
||||||
uint32_t EMSESP::last_fetch_ = 0;
|
uint8_t EMSESP::publish_all_idx_ = 0;
|
||||||
uint8_t EMSESP::publish_all_idx_ = 0;
|
uint8_t EMSESP::unique_id_count_ = 0;
|
||||||
uint8_t EMSESP::unique_id_count_ = 0;
|
bool EMSESP::trace_raw_ = false;
|
||||||
bool EMSESP::trace_raw_ = false;
|
uint16_t EMSESP::wait_validate_ = 0;
|
||||||
uint16_t EMSESP::wait_validate_ = 0;
|
bool EMSESP::wait_km_ = true;
|
||||||
bool EMSESP::wait_km_ = true;
|
|
||||||
|
|
||||||
// for a specific EMS device go and request data values
|
// for a specific EMS device go and request data values
|
||||||
// or if device_id is 0 it will fetch from all our known and active devices
|
// or if device_id is 0 it will fetch from all our known and active devices
|
||||||
@@ -168,63 +167,6 @@ void EMSESP::scan_devices() {
|
|||||||
EMSESP::send_read_request(EMSdevice::EMS_TYPE_UBADevices, EMSdevice::EMS_DEVICE_ID_BOILER);
|
EMSESP::send_read_request(EMSdevice::EMS_TYPE_UBADevices, EMSdevice::EMS_DEVICE_ID_BOILER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* if thermostat master is 0x18 it handles only ww and hc1, hc2..hc8 handled by devices 0x19..0x1F
|
|
||||||
* we send to right device and match all reads to 0x18
|
|
||||||
*/
|
|
||||||
uint8_t EMSESP::check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read) {
|
|
||||||
if (device_id != 0x10 && (device_id < 0x18 || device_id > 0x1F)) {
|
|
||||||
return device_id;
|
|
||||||
}
|
|
||||||
if (actual_master_thermostat_ == 0x18) {
|
|
||||||
uint16_t mon_ids[] = {0x02A5, 0x02A6, 0x02A7, 0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC};
|
|
||||||
uint16_t set_ids[] = {0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF, 0x02C0};
|
|
||||||
uint16_t summer_ids[] = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
|
|
||||||
uint16_t curve_ids[] = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
|
|
||||||
uint16_t summer2_ids[] = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
|
|
||||||
uint16_t master_ids[] = {0x02F5, 0x031B, 0x031D, 0x031E, 0x023A, 0x0267, 0x0240};
|
|
||||||
// look for heating circuits
|
|
||||||
for (uint8_t i = 0; i < sizeof(mon_ids) / 2; i++) {
|
|
||||||
if (type_id == mon_ids[i] || type_id == set_ids[i] || type_id == summer_ids[i] || type_id == curve_ids[i] || type_id == summer2_ids[i]) {
|
|
||||||
if (read) {
|
|
||||||
// receiving telegrams and map all to master thermostat at 0x18 (src manipulated)
|
|
||||||
return 0x18;
|
|
||||||
} else {
|
|
||||||
// sending telegrams to the individual thermostats (dst manipulated)
|
|
||||||
return 0x18 + i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// look for ids that are only handled by master
|
|
||||||
for (uint8_t i = 0; i < sizeof(master_ids) / 2; i++) {
|
|
||||||
if (type_id == master_ids[i]) {
|
|
||||||
return 0x18;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (actual_master_thermostat_ == 0x10) {
|
|
||||||
// Junkers FW200 supports hc1/hc2, hc3/hc4 handled by devices 0x1A...
|
|
||||||
// see https://github.com/emsesp/EMS-ESP32/issues/336
|
|
||||||
uint16_t mon_ids[] = {0x0171, 0x0172};
|
|
||||||
uint16_t set_ids[] = {0x0167, 0x0168};
|
|
||||||
for (uint8_t i = 0; i < sizeof(mon_ids) / 2; i++) {
|
|
||||||
if (type_id == mon_ids[i] || type_id == set_ids[i]) {
|
|
||||||
// reads to master thermostat, writes to remote thermostats
|
|
||||||
return (read ? actual_master_thermostat_ : 0x1A + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return device_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EMSESP::actual_master_thermostat(const uint8_t device_id) {
|
|
||||||
actual_master_thermostat_ = device_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t EMSESP::actual_master_thermostat() {
|
|
||||||
return actual_master_thermostat_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to watch both type IDs and deviceIDs
|
// to watch both type IDs and deviceIDs
|
||||||
void EMSESP::watch_id(uint16_t watch_id) {
|
void EMSESP::watch_id(uint16_t watch_id) {
|
||||||
watch_id_ = watch_id;
|
watch_id_ = watch_id;
|
||||||
@@ -560,13 +502,13 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
bool nested = (Mqtt::is_nested());
|
bool nested = (Mqtt::is_nested());
|
||||||
|
|
||||||
// group by device type
|
// group by device type
|
||||||
for (const auto & emsdevice : emsdevices) {
|
if (Mqtt::ha_enabled()) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
// specially for MQTT Discovery
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
// we may have some RETAINED /config topics that reference fields in the data payloads that no longer exist
|
// specially for MQTT Discovery
|
||||||
// remove them immediately to prevent HA from complaining
|
// we may have some RETAINED /config topics that reference fields in the data payloads that no longer exist
|
||||||
// we need to do this first before the data payload is published, and only done once!
|
// remove them immediately to prevent HA from complaining
|
||||||
if (Mqtt::ha_enabled()) {
|
// we need to do this first before the data payload is published, and only done once!
|
||||||
if (emsdevice->ha_config_firstrun()) {
|
if (emsdevice->ha_config_firstrun()) {
|
||||||
emsdevice->ha_config_clear();
|
emsdevice->ha_config_clear();
|
||||||
emsdevice->ha_config_firstrun(false);
|
emsdevice->ha_config_firstrun(false);
|
||||||
@@ -575,79 +517,40 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
emsdevice->mqtt_ha_entity_config_remove();
|
emsdevice->mqtt_ha_entity_config_remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if its a boiler, generate json for each group and publish it directly. not nested
|
|
||||||
if (device_type == DeviceType::BOILER) {
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
if (emsdevice->generate_values(json, DeviceValueTAG::TAG_BOILER_DATA, false, EMSdevice::OUTPUT_TARGET::MQTT)) {
|
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_BOILER_DATA), json);
|
|
||||||
}
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
if (emsdevice->generate_values(json, DeviceValueTAG::TAG_DEVICE_DATA_WW, false, EMSdevice::OUTPUT_TARGET::MQTT)) {
|
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_DEVICE_DATA_WW), json);
|
|
||||||
}
|
|
||||||
need_publish = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thermostat
|
|
||||||
else if (device_type == DeviceType::THERMOSTAT) {
|
|
||||||
// only publish the single master thermostat
|
|
||||||
if (emsdevice->device_id() == EMSESP::actual_master_thermostat()) {
|
|
||||||
if (nested) {
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::MQTT); // nested
|
|
||||||
} else {
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_THERMOSTAT_DATA, false, EMSdevice::OUTPUT_TARGET::MQTT); // not nested
|
|
||||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_DEVICE_DATA_WW, false, EMSdevice::OUTPUT_TARGET::MQTT);
|
|
||||||
if (need_publish) {
|
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_NONE), json);
|
|
||||||
}
|
|
||||||
for (uint8_t hc_tag = DeviceValueTAG::TAG_HC1; hc_tag <= DeviceValueTAG::TAG_HC8; hc_tag++) {
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
if (emsdevice->generate_values(json, hc_tag, false, EMSdevice::OUTPUT_TARGET::MQTT)) { // not nested
|
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, hc_tag), json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
need_publish = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mixer
|
|
||||||
else if (device_type == DeviceType::MIXER) {
|
|
||||||
if (nested) {
|
|
||||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::MQTT); // nested
|
|
||||||
} else {
|
|
||||||
for (uint8_t hc_tag = DeviceValueTAG::TAG_HC1; hc_tag <= DeviceValueTAG::TAG_WWC10; hc_tag++) {
|
|
||||||
json = doc.to<JsonObject>();
|
|
||||||
if (emsdevice->generate_values(json, hc_tag, false, EMSdevice::OUTPUT_TARGET::MQTT)) { // not nested
|
|
||||||
Mqtt::publish(Mqtt::tag_to_topic(device_type, hc_tag), json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
need_publish = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// for all other devices add the values to the json
|
|
||||||
need_publish |= emsdevice->generate_values(json, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::MQTT); // nested
|
|
||||||
}
|
|
||||||
|
|
||||||
// we want to create the /config topic after the data payload to prevent HA from throwing up a warning
|
|
||||||
if (Mqtt::ha_enabled()) {
|
|
||||||
emsdevice->mqtt_ha_entity_config_create();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (uint8_t tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
|
||||||
// publish it under a single topic, only if we have data to publish
|
JsonObject json_hc = json;
|
||||||
|
bool nest_created = false;
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
|
if (nested && !nest_created && emsdevice->has_tag(tag)) {
|
||||||
|
json_hc = doc.createNestedObject(EMSdevice::tag_to_string(tag));
|
||||||
|
nest_created = true;
|
||||||
|
}
|
||||||
|
need_publish |= emsdevice->generate_values(json_hc, tag, false, EMSdevice::OUTPUT_TARGET::MQTT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (need_publish && ((!nested && tag >= DeviceValueTAG::TAG_DEVICE_DATA_WW) || (tag == DeviceValueTAG::TAG_BOILER_DATA_WW))) {
|
||||||
|
Mqtt::publish(Mqtt::tag_to_topic(device_type, tag), json);
|
||||||
|
json = doc.to<JsonObject>();
|
||||||
|
need_publish = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (need_publish) {
|
if (need_publish) {
|
||||||
if (doc.overflowed()) {
|
if (doc.overflowed()) {
|
||||||
LOG_WARNING(F("MQTT buffer overflow, please use individual topics"));
|
LOG_WARNING(F("MQTT buffer overflow, please use individual topics"));
|
||||||
}
|
}
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
Mqtt::publish(Mqtt::tag_to_topic(device_type, DeviceValueTAG::TAG_NONE), json);
|
||||||
snprintf(topic, sizeof(topic), "%s_data", EMSdevice::device_type_2_device_name(device_type).c_str());
|
}
|
||||||
Mqtt::publish(topic, json);
|
|
||||||
|
// we want to create the /config topic after the data payload to prevent HA from throwing up a warning
|
||||||
|
if (Mqtt::ha_enabled()) {
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
|
emsdevice->mqtt_ha_entity_config_create();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,7 +645,6 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
std::string src_name("");
|
std::string src_name("");
|
||||||
std::string dest_name("");
|
std::string dest_name("");
|
||||||
std::string type_name("");
|
std::string type_name("");
|
||||||
std::string direction("");
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice) {
|
if (emsdevice) {
|
||||||
// get src & dest
|
// get src & dest
|
||||||
@@ -779,16 +681,15 @@ std::string EMSESP::pretty_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
type_name = read_flash_string(F("?"));
|
type_name = read_flash_string(F("?"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (telegram->operation == Telegram::Operation::RX_READ) {
|
|
||||||
direction = read_flash_string(F("<-"));
|
|
||||||
} else {
|
|
||||||
direction = read_flash_string(F("->"));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string str;
|
std::string str;
|
||||||
str.reserve(200);
|
str.reserve(200);
|
||||||
str = src_name + "(" + Helpers::hextoa(src) + ") " + direction + " " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
if (telegram->operation == Telegram::Operation::RX_READ) {
|
||||||
+ Helpers::hextoa(telegram->type_id) + "), data: " + telegram->to_string_message();
|
str = src_name + "(" + Helpers::hextoa(src) + ") <- " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
||||||
|
+ Helpers::hextoa(telegram->type_id) + "), length: " + Helpers::hextoa(telegram->message_data[0]);
|
||||||
|
} else {
|
||||||
|
str = src_name + "(" + Helpers::hextoa(src) + ") -> " + dest_name + "(" + Helpers::hextoa(dest) + "), " + type_name + "("
|
||||||
|
+ Helpers::hextoa(telegram->type_id) + "), data: " + telegram->to_string_message();
|
||||||
|
}
|
||||||
|
|
||||||
if (offset) {
|
if (offset) {
|
||||||
str += " (offset " + Helpers::itoa(offset) + ")";
|
str += " (offset " + Helpers::itoa(offset) + ")";
|
||||||
@@ -925,16 +826,13 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
// match device_id and type_id
|
// match device_id and type_id
|
||||||
// calls the associated process function for that EMS device
|
// calls the associated process function for that EMS device
|
||||||
// returns false if the device_id doesn't recognize it
|
// returns false if the device_id doesn't recognize it
|
||||||
// after the telegram has been processed, call see if there have been values changed and we need to do a MQTT publish
|
// after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool knowndevice = false;
|
bool knowndevice = false;
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice->is_device_id(telegram->src) || emsdevice->is_device_id(telegram->dest)) {
|
if (emsdevice->is_device_id(telegram->src)) {
|
||||||
knowndevice = true;
|
knowndevice = true;
|
||||||
found = emsdevice->handle_telegram(telegram);
|
found = emsdevice->handle_telegram(telegram);
|
||||||
if (found && emsdevice->is_device_id(telegram->dest)) {
|
|
||||||
LOG_DEBUG(F("Process setting 0x%02X for device 0x%02X"), telegram->type_id, telegram->dest);
|
|
||||||
}
|
|
||||||
// if we correctly processed the telegram then follow up with sending it via MQTT (if enabled)
|
// if we correctly processed the telegram then follow up with sending it via MQTT (if enabled)
|
||||||
if (found && Mqtt::connected()) {
|
if (found && Mqtt::connected()) {
|
||||||
if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update())
|
if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update())
|
||||||
@@ -951,7 +849,7 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
|||||||
if (wait_validate_ == telegram->type_id) {
|
if (wait_validate_ == telegram->type_id) {
|
||||||
wait_validate_ = 0;
|
wait_validate_ = 0;
|
||||||
}
|
}
|
||||||
if (!found && emsdevice->is_device_id(telegram->src) && telegram->message_length > 0) {
|
if (!found && telegram->message_length > 0) {
|
||||||
emsdevice->add_handlers_ignored(telegram->type_id);
|
emsdevice->add_handlers_ignored(telegram->type_id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1007,10 +905,6 @@ void EMSESP::show_devices(uuid::console::Shell & shell) {
|
|||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
if (emsdevice && (emsdevice->device_type() == device_class.first)) {
|
||||||
shell.printf(F("%s: %s"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str());
|
shell.printf(F("%s: %s"), emsdevice->device_type_name().c_str(), emsdevice->to_string().c_str());
|
||||||
if ((num_thermostats > 1) && (emsdevice->device_type() == EMSdevice::DeviceType::THERMOSTAT)
|
|
||||||
&& (emsdevice->device_id() == actual_master_thermostat())) {
|
|
||||||
shell.printf(F(" **master device**"));
|
|
||||||
}
|
|
||||||
shell.println();
|
shell.println();
|
||||||
emsdevice->show_telegram_handlers(shell);
|
emsdevice->show_telegram_handlers(shell);
|
||||||
|
|
||||||
@@ -1034,6 +928,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
// first check to see if we already have it, if so update the record
|
// first check to see if we already have it, if so update the record
|
||||||
for (const auto & emsdevice : emsdevices) {
|
for (const auto & emsdevice : emsdevices) {
|
||||||
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
if (emsdevice && emsdevice->is_device_id(device_id)) {
|
||||||
|
if (product_id == 0) { // update only with valid product_id
|
||||||
|
return true;
|
||||||
|
}
|
||||||
LOG_DEBUG(F("Updating details for already active deviceID 0x%02X"), device_id);
|
LOG_DEBUG(F("Updating details for already active deviceID 0x%02X"), device_id);
|
||||||
emsdevice->product_id(product_id);
|
emsdevice->product_id(product_id);
|
||||||
emsdevice->version(version);
|
emsdevice->version(version);
|
||||||
@@ -1058,9 +955,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
for (auto & device : device_library_) {
|
for (auto & device : device_library_) {
|
||||||
if (device.product_id == product_id) {
|
if (device.product_id == product_id) {
|
||||||
// sometimes boilers share the same productID as controllers
|
// sometimes boilers share the same productID as controllers
|
||||||
// so only add boilers if the device_id is 0x08, which is fixed for EMS
|
// so only add boilers if the device_id is 0x08 or 0x60 or 0x70.., which is fixed for EMS
|
||||||
if (device.device_type == DeviceType::BOILER) {
|
if (device.device_type == DeviceType::BOILER) {
|
||||||
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER
|
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER || device_id == EMSdevice::EMS_DEVICE_ID_AM200
|
||||||
|| (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1 && device_id <= EMSdevice::EMS_DEVICE_ID_BOILER_F)) {
|
|| (device_id >= EMSdevice::EMS_DEVICE_ID_BOILER_1 && device_id <= EMSdevice::EMS_DEVICE_ID_BOILER_F)) {
|
||||||
device_p = &device;
|
device_p = &device;
|
||||||
break;
|
break;
|
||||||
@@ -1203,23 +1100,36 @@ bool EMSESP::command_commands(uint8_t device_type, JsonObject & output, const in
|
|||||||
bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target) {
|
bool EMSESP::command_info(uint8_t device_type, JsonObject & output, const int8_t id, const uint8_t output_target) {
|
||||||
bool has_value = false;
|
bool has_value = false;
|
||||||
uint8_t tag;
|
uint8_t tag;
|
||||||
if (id >= 1 && id <= 8) {
|
if (id >= 1 && id <= (1 + DeviceValueTAG::TAG_HS16 - DeviceValueTAG::TAG_HC1)) {
|
||||||
tag = DeviceValueTAG::TAG_HC1 + id - 1;
|
tag = DeviceValueTAG::TAG_HC1 + id - 1; // this sets also WWC and HS
|
||||||
} else if (id >= 9 && id <= 19) {
|
|
||||||
tag = DeviceValueTAG::TAG_WWC1 + id - 9;
|
|
||||||
} else if (id == -1 || id == 0) {
|
} else if (id == -1 || id == 0) {
|
||||||
tag = DeviceValueTAG::TAG_NONE;
|
tag = DeviceValueTAG::TAG_NONE;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
if (id > 0 || output_target == EMSdevice::OUTPUT_TARGET::API_VERBOSE) {
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)
|
for (const auto & emsdevice : emsdevices) {
|
||||||
&& ((device_type != DeviceType::THERMOSTAT) || (emsdevice->device_id() == EMSESP::actual_master_thermostat()))) {
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
has_value |= emsdevice->generate_values(output, tag, (id < 1), output_target); // use nested for id -1 and 0
|
has_value |= emsdevice->generate_values(output, tag, (id < 1), output_target); // use nested for id -1 and 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return has_value;
|
||||||
|
}
|
||||||
|
// for nested output add for each tag
|
||||||
|
for (tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
|
||||||
|
JsonObject output_hc = output;
|
||||||
|
bool nest_created = false;
|
||||||
|
for (const auto & emsdevice : emsdevices) {
|
||||||
|
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
||||||
|
if (!nest_created && emsdevice->has_tag(tag)) {
|
||||||
|
output_hc = output.createNestedObject(EMSdevice::tag_to_string(tag));
|
||||||
|
nest_created = true;
|
||||||
|
}
|
||||||
|
has_value |= emsdevice->generate_values(output_hc, tag, true, output_target); // use nested for id -1 and 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return has_value;
|
return has_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1373,8 +1283,8 @@ void EMSESP::start() {
|
|||||||
|
|
||||||
// start the file system
|
// start the file system
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (!LITTLEFS.begin(true)) {
|
if (!LittleFS.begin(true)) {
|
||||||
Serial.println("LITTLEFS Mount failed. EMS-ESP stopped.");
|
Serial.println("LittleFS Mount Failed. EMS-ESP stopped.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -134,10 +134,6 @@ class EMSESP {
|
|||||||
static uint8_t count_devices();
|
static uint8_t count_devices();
|
||||||
static uint8_t device_index(const uint8_t device_type, const uint8_t unique_id);
|
static uint8_t device_index(const uint8_t device_type, const uint8_t unique_id);
|
||||||
|
|
||||||
static uint8_t actual_master_thermostat();
|
|
||||||
static void actual_master_thermostat(const uint8_t device_id);
|
|
||||||
static uint8_t check_master_device(const uint8_t device_id, const uint16_t type_id, const bool read);
|
|
||||||
|
|
||||||
static bool get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype);
|
static bool get_device_value_info(JsonObject & root, const char * cmd, const int8_t id, const uint8_t devicetype);
|
||||||
|
|
||||||
static void show_device_values(uuid::console::Shell & shell);
|
static void show_device_values(uuid::console::Shell & shell);
|
||||||
@@ -261,7 +257,6 @@ class EMSESP {
|
|||||||
};
|
};
|
||||||
static std::vector<Device_record> device_library_;
|
static std::vector<Device_record> device_library_;
|
||||||
|
|
||||||
static uint8_t actual_master_thermostat_;
|
|
||||||
static uint16_t watch_id_;
|
static uint16_t watch_id_;
|
||||||
static uint8_t watch_;
|
static uint8_t watch_;
|
||||||
static uint16_t read_id_;
|
static uint16_t read_id_;
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ char * Helpers::hextoa(char * result, const uint16_t value) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// same as above but to a hex string
|
// same as above but to a hex string
|
||||||
std::string Helpers::hextoa(const uint16_t value, bool prefix) {
|
std::string Helpers::hextoa(const uint16_t value, bool prefix) {
|
||||||
char buf[5];
|
char buf[5];
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ MAKE_PSTR_WORD(reconnect)
|
|||||||
MAKE_PSTR_WORD(ssid)
|
MAKE_PSTR_WORD(ssid)
|
||||||
MAKE_PSTR_WORD(heartbeat)
|
MAKE_PSTR_WORD(heartbeat)
|
||||||
MAKE_PSTR_WORD(users)
|
MAKE_PSTR_WORD(users)
|
||||||
MAKE_PSTR_WORD(master)
|
|
||||||
MAKE_PSTR_WORD(pin)
|
|
||||||
MAKE_PSTR_WORD(publish)
|
MAKE_PSTR_WORD(publish)
|
||||||
MAKE_PSTR_WORD(timeout)
|
MAKE_PSTR_WORD(timeout)
|
||||||
MAKE_PSTR_WORD(board_profile)
|
MAKE_PSTR_WORD(board_profile)
|
||||||
@@ -105,7 +103,6 @@ MAKE_PSTR_WORD(unknown)
|
|||||||
MAKE_PSTR_WORD(dallassensor)
|
MAKE_PSTR_WORD(dallassensor)
|
||||||
|
|
||||||
// format strings
|
// format strings
|
||||||
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat Device ID: %s")
|
|
||||||
MAKE_PSTR(host_fmt, "Host: %s")
|
MAKE_PSTR(host_fmt, "Host: %s")
|
||||||
MAKE_PSTR(port_fmt, "Port: %d")
|
MAKE_PSTR(port_fmt, "Port: %d")
|
||||||
MAKE_PSTR(hostname_fmt, "Hostname: %s")
|
MAKE_PSTR(hostname_fmt, "Hostname: %s")
|
||||||
@@ -206,9 +203,9 @@ MAKE_PSTR(l, "l")
|
|||||||
// mqtt tags must not have spaces
|
// mqtt tags must not have spaces
|
||||||
MAKE_PSTR(tag_none, "")
|
MAKE_PSTR(tag_none, "")
|
||||||
MAKE_PSTR(tag_heartbeat, "")
|
MAKE_PSTR(tag_heartbeat, "")
|
||||||
MAKE_PSTR(tag_boiler_data, "")
|
MAKE_PSTR(tag_boiler_data_ww, "ww")
|
||||||
MAKE_PSTR(tag_device_data_ww, "Warmwasser")
|
MAKE_PSTR(tag_device_data, "")
|
||||||
MAKE_PSTR(tag_thermostat_data, "")
|
MAKE_PSTR(tag_device_data_ww, "ww")
|
||||||
MAKE_PSTR(tag_hc1, "hc1")
|
MAKE_PSTR(tag_hc1, "hc1")
|
||||||
MAKE_PSTR(tag_hc2, "hc2")
|
MAKE_PSTR(tag_hc2, "hc2")
|
||||||
MAKE_PSTR(tag_hc3, "hc3")
|
MAKE_PSTR(tag_hc3, "hc3")
|
||||||
@@ -227,6 +224,7 @@ MAKE_PSTR(tag_wwc7, "wwc7")
|
|||||||
MAKE_PSTR(tag_wwc8, "wwc8")
|
MAKE_PSTR(tag_wwc8, "wwc8")
|
||||||
MAKE_PSTR(tag_wwc9, "wwc9")
|
MAKE_PSTR(tag_wwc9, "wwc9")
|
||||||
MAKE_PSTR(tag_wwc10, "wwc10")
|
MAKE_PSTR(tag_wwc10, "wwc10")
|
||||||
|
MAKE_PSTR(tag_ahs, "ahs")
|
||||||
MAKE_PSTR(tag_hs1, "hs1")
|
MAKE_PSTR(tag_hs1, "hs1")
|
||||||
MAKE_PSTR(tag_hs2, "hs2")
|
MAKE_PSTR(tag_hs2, "hs2")
|
||||||
MAKE_PSTR(tag_hs3, "hs3")
|
MAKE_PSTR(tag_hs3, "hs3")
|
||||||
@@ -246,8 +244,9 @@ MAKE_PSTR(tag_hs16, "hs16")
|
|||||||
|
|
||||||
// MQTT topic names
|
// MQTT topic names
|
||||||
// MAKE_PSTR(tag_heartbeat_mqtt, "heartbeat")
|
// MAKE_PSTR(tag_heartbeat_mqtt, "heartbeat")
|
||||||
MAKE_PSTR(tag_boiler_data_mqtt, "")
|
// MAKE_PSTR(tag_boiler_data_mqtt, "")
|
||||||
MAKE_PSTR(tag_device_data_ww_mqtt, "ww")
|
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
|
||||||
|
MAKE_PSTR(tag_device_data_ww_mqtt, "")
|
||||||
|
|
||||||
// boiler
|
// boiler
|
||||||
MAKE_PSTR(time, "Zeit")
|
MAKE_PSTR(time, "Zeit")
|
||||||
@@ -262,6 +261,7 @@ MAKE_PSTR_(continuos, "kontinuierlich")
|
|||||||
MAKE_PSTR(3wayvalve, "3-Wege Ventil")
|
MAKE_PSTR(3wayvalve, "3-Wege Ventil")
|
||||||
MAKE_PSTR(chargepump, "Ladepumpe")
|
MAKE_PSTR(chargepump, "Ladepumpe")
|
||||||
MAKE_PSTR(hot, "Heiss")
|
MAKE_PSTR(hot, "Heiss")
|
||||||
|
MAKE_PSTR(high_comfort, "Heiss Komfort")
|
||||||
MAKE_PSTR(eco, "Eco")
|
MAKE_PSTR(eco, "Eco")
|
||||||
MAKE_PSTR(intelligent, "Intelligent")
|
MAKE_PSTR(intelligent, "Intelligent")
|
||||||
MAKE_PSTR_(flow, "Fluss")
|
MAKE_PSTR_(flow, "Fluss")
|
||||||
@@ -270,6 +270,8 @@ MAKE_PSTR_(buffer, "Speicher")
|
|||||||
MAKE_PSTR(bufferedflow, "Durchlaufspeicher")
|
MAKE_PSTR(bufferedflow, "Durchlaufspeicher")
|
||||||
MAKE_PSTR(layeredbuffer, "Schichtspeicher")
|
MAKE_PSTR(layeredbuffer, "Schichtspeicher")
|
||||||
MAKE_PSTR(maintenance, "Wartung")
|
MAKE_PSTR(maintenance, "Wartung")
|
||||||
|
MAKE_PSTR(heating, "Heizen")
|
||||||
|
MAKE_PSTR(cooling, "K<EFBFBD>hlen")
|
||||||
|
|
||||||
// boiler lists
|
// boiler lists
|
||||||
MAKE_PSTR_LIST(tpl_date, F("Format: < dd.mm.yyyy >")) // template for text input
|
MAKE_PSTR_LIST(tpl_date, F("Format: < dd.mm.yyyy >")) // template for text input
|
||||||
@@ -277,10 +279,19 @@ MAKE_PSTR_LIST(enum_off_time_date_manual, F_(off), F_(time), F_(date), F_(manual
|
|||||||
MAKE_PSTR_LIST(enum_freq, F_(off), F_(1x3min), F_(2x3min), F_(3x3min), F_(4x3min), F_(5x3min), F_(6x3min), F_(continuous))
|
MAKE_PSTR_LIST(enum_freq, F_(off), F_(1x3min), F_(2x3min), F_(3x3min), F_(4x3min), F_(5x3min), F_(6x3min), F_(continuous))
|
||||||
MAKE_PSTR_LIST(enum_charge, F_(chargepump), F_(3wayvalve))
|
MAKE_PSTR_LIST(enum_charge, F_(chargepump), F_(3wayvalve))
|
||||||
MAKE_PSTR_LIST(enum_comfort, F_(hot), F_(eco), F_(intelligent))
|
MAKE_PSTR_LIST(enum_comfort, F_(hot), F_(eco), F_(intelligent))
|
||||||
|
MAKE_PSTR_LIST(enum_comfort1, F_(high_comfort), F_(eco))
|
||||||
MAKE_PSTR_LIST(enum_flow, F_(off), F_(flow), F_(bufferedflow), F_(buffer), F_(layeredbuffer))
|
MAKE_PSTR_LIST(enum_flow, F_(off), F_(flow), F_(bufferedflow), F_(buffer), F_(layeredbuffer))
|
||||||
MAKE_PSTR_LIST(enum_reset, F("-"), F_(maintenance), F_(error))
|
MAKE_PSTR_LIST(enum_reset, F("-"), F_(maintenance), F_(error))
|
||||||
// MAKE_PSTR_LIST(enum_bool, F_(off), F_(on))
|
// MAKE_PSTR_LIST(enum_bool, F_(off), F_(on))
|
||||||
|
|
||||||
|
// AM200 lists
|
||||||
|
MAKE_PSTR_LIST(enum_vr2Config, F_(off), F("bypass"));
|
||||||
|
MAKE_PSTR_LIST(enum_aPumpSignal, F_(off), F("pwm"), F("pwm_invers"));
|
||||||
|
MAKE_PSTR_LIST(enum_bufBypass, F("no"), F_(mixer), F("valve"));
|
||||||
|
MAKE_PSTR_LIST(enum_bufConfig, F("monovalent"), F("bivalent"));
|
||||||
|
MAKE_PSTR_LIST(enum_blockMode, F_(off), F_(auto), F("blocking"));
|
||||||
|
MAKE_PSTR_LIST(enum_blockTerm, F("n_o"), F("n_c"));
|
||||||
|
|
||||||
//heatpump
|
//heatpump
|
||||||
MAKE_PSTR_LIST(enum_hpactivity, F("Kein"), F("Heizen"), F("Kühlen"), F("Warmwasser"), F("Pool"))
|
MAKE_PSTR_LIST(enum_hpactivity, F("Kein"), F("Heizen"), F("Kühlen"), F("Warmwasser"), F("Pool"))
|
||||||
|
|
||||||
@@ -311,6 +322,7 @@ MAKE_PSTR(winter, "Winter")
|
|||||||
MAKE_PSTR(outdoor, "Aussentemperatur")
|
MAKE_PSTR(outdoor, "Aussentemperatur")
|
||||||
MAKE_PSTR_WORD(mpc)
|
MAKE_PSTR_WORD(mpc)
|
||||||
MAKE_PSTR(room, "Raum")
|
MAKE_PSTR(room, "Raum")
|
||||||
|
MAKE_PSTR(room_outdoor, "Raum+Au<41>en")
|
||||||
MAKE_PSTR(power, "Leistung")
|
MAKE_PSTR(power, "Leistung")
|
||||||
MAKE_PSTR(constant, "konstant")
|
MAKE_PSTR(constant, "konstant")
|
||||||
MAKE_PSTR(simple, "einfach")
|
MAKE_PSTR(simple, "einfach")
|
||||||
@@ -358,7 +370,7 @@ MAKE_PSTR_LIST(enum_ibaLanguage_RC30, F_(german), F_(dutch))
|
|||||||
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
||||||
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy)) // RC300
|
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy)) // RC300
|
||||||
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
||||||
MAKE_PSTR_LIST(enum_wwMode, F_(off), F_(low), F_(high), F_(auto), F_(own_prog))
|
MAKE_PSTR_LIST(enum_wwMode, F_(off), F("normal"), F_(comfort), F_(auto), F_(own_prog), F_(eco))
|
||||||
MAKE_PSTR_LIST(enum_wwCircMode, F_(off), F_(on), F_(auto), F_(own_prog))
|
MAKE_PSTR_LIST(enum_wwCircMode, F_(off), F_(on), F_(auto), F_(own_prog))
|
||||||
MAKE_PSTR_LIST(enum_wwMode2, F_(off), F_(on), F_(auto))
|
MAKE_PSTR_LIST(enum_wwMode2, F_(off), F_(on), F_(auto))
|
||||||
MAKE_PSTR_LIST(enum_wwMode3, F_(on), F_(off), F_(auto))
|
MAKE_PSTR_LIST(enum_wwMode3, F_(on), F_(off), F_(auto))
|
||||||
@@ -366,6 +378,7 @@ MAKE_PSTR_LIST(enum_heatingtype, F_(off), F_(radiator), F_(convector), F_(floor)
|
|||||||
MAKE_PSTR_LIST(enum_summermode, F_(summer), F_(auto), F_(winter))
|
MAKE_PSTR_LIST(enum_summermode, F_(summer), F_(auto), F_(winter))
|
||||||
MAKE_PSTR_LIST(enum_hpoperatingmode, F_(off), F_(auto), F("heizen"), F("kühlen"))
|
MAKE_PSTR_LIST(enum_hpoperatingmode, F_(off), F_(auto), F("heizen"), F("kühlen"))
|
||||||
MAKE_PSTR_LIST(enum_summer, F_(winter), F_(summer))
|
MAKE_PSTR_LIST(enum_summer, F_(winter), F_(summer))
|
||||||
|
MAKE_PSTR_LIST(enum_operatingstate, F_(heating), F_(off), F_(cooling))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_mode, F_(manual), F_(auto)) // RC100, RC300, RC310
|
MAKE_PSTR_LIST(enum_mode, F_(manual), F_(auto)) // RC100, RC300, RC310
|
||||||
MAKE_PSTR_LIST(enum_mode2, F_(off), F_(manual), F_(auto)) // RC20
|
MAKE_PSTR_LIST(enum_mode2, F_(off), F_(manual), F_(auto)) // RC20
|
||||||
@@ -381,9 +394,12 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
|
|||||||
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_reducemode1, F_(outdoor), F_(room), F_(reduce)) // RC310 values: 1-3
|
||||||
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_nofrostmode1, F_(room), F_(outdoor), F_(room_outdoor))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
||||||
|
MAKE_PSTR_LIST(enum_controlmode1, F("weather-compensated"), F("outside-basepoint"), F("n/a"), F_(room)) // RC310 1-4
|
||||||
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
||||||
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
|
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
|
||||||
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
|
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
|
||||||
@@ -474,6 +490,8 @@ MAKE_PSTR_LIST(maintenanceMessage, F("maintenancemessage"), F("Wartungsmeldung")
|
|||||||
MAKE_PSTR_LIST(maintenanceDate, F("maintenancedate"), F("Wartungsdatum"))
|
MAKE_PSTR_LIST(maintenanceDate, F("maintenancedate"), F("Wartungsdatum"))
|
||||||
MAKE_PSTR_LIST(maintenanceType, F_(maintenance), F("Wartungsplan"))
|
MAKE_PSTR_LIST(maintenanceType, F_(maintenance), F("Wartungsplan"))
|
||||||
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("Wartung in"))
|
MAKE_PSTR_LIST(maintenanceTime, F("maintenancetime"), F("Wartung in"))
|
||||||
|
MAKE_PSTR_LIST(emergencyOps, F("emergencyops"), F("emergency operation"))
|
||||||
|
MAKE_PSTR_LIST(emergencyTemp, F("emergencytemp"), F("emergency temperature"))
|
||||||
|
|
||||||
// heatpump/compress specific
|
// heatpump/compress specific
|
||||||
MAKE_PSTR_LIST(upTimeControl, F("uptimecontrol"), F("Betriebszeit total heizen"))
|
MAKE_PSTR_LIST(upTimeControl, F("uptimecontrol"), F("Betriebszeit total heizen"))
|
||||||
@@ -538,6 +556,37 @@ MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor"))
|
|||||||
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
||||||
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
||||||
|
|
||||||
|
// alternative heatsource AM200
|
||||||
|
MAKE_PSTR_LIST(aCylTopTemp, F("cyltoptemp"), F("Zylinder oben Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(aCylCenterTemp, F("cylcentertemp"), F("Zylinder mitte Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(aCylBottomTemp, F("cylbottomtemp"), F("Zylinder unten Temperatur"))
|
||||||
|
MAKE_PSTR_LIST(aFlowTemp, F("altflowtemp"), F("Alternativ hs Flusstemperatur"))
|
||||||
|
MAKE_PSTR_LIST(aRetTemp, F("altrettemp"), F("Alternativ hs Rücktemperatur"))
|
||||||
|
MAKE_PSTR_LIST(sysFlowTemp, F("sysflowtemp"), F("System Flusstemperature"))
|
||||||
|
MAKE_PSTR_LIST(sysRetTemp, F("sysrettemp"), F("System Rücktemperature"))
|
||||||
|
MAKE_PSTR_LIST(valveByPass, F("valvebypass"), F("bypass Ventil"))
|
||||||
|
MAKE_PSTR_LIST(valveBuffer, F("valvebuffer"), F("Puffer Ventil"))
|
||||||
|
MAKE_PSTR_LIST(valveReturn, F("valvereturn"), F("Rückfluss Ventil"))
|
||||||
|
MAKE_PSTR_LIST(aPumpMod, F("altpumpmod"), F("Alternativ hs Pumpenmodulation"))
|
||||||
|
MAKE_PSTR_LIST(heatSource, F("heatsource"), F("Alternativ Heizung"))
|
||||||
|
|
||||||
|
MAKE_PSTR_LIST(vr2Config, F("vr2config"), F("vr2 configuration"))
|
||||||
|
MAKE_PSTR_LIST(ahsActivated, F("ahsactivated"), F("alternate heat source activation"))
|
||||||
|
MAKE_PSTR_LIST(aPumpConfig, F("apumpconfig"), F("primary pump config"))
|
||||||
|
MAKE_PSTR_LIST(aPumpSignal, F("apumpsignal"), F("output for pr1 pump"))
|
||||||
|
MAKE_PSTR_LIST(aPumpMin, F("apumpmin"), F("min output pump pr1"))
|
||||||
|
MAKE_PSTR_LIST(tempRise, F("temprise"), F("ahs return temp rise"))
|
||||||
|
MAKE_PSTR_LIST(setReturnTemp, F("setreturntemp"), F("set temp return"))
|
||||||
|
MAKE_PSTR_LIST(mixRuntime, F("mixruntime"), F("mixer run time"))
|
||||||
|
// MAKE_PSTR_LIST(setFlowTemp, F("setflowtemp"), F("set flow temp"))
|
||||||
|
MAKE_PSTR_LIST(bufBypass, F("bufbypass"), F("buffer bypass config"))
|
||||||
|
MAKE_PSTR_LIST(bufMixRuntime, F("bufmixruntime"), F("bypass mixer run time"))
|
||||||
|
MAKE_PSTR_LIST(bufConfig, F("bufconfig"), F("dhw buffer config"))
|
||||||
|
MAKE_PSTR_LIST(blockMode, F("blockmode"), F("config htg. blocking mode"))
|
||||||
|
MAKE_PSTR_LIST(blockTerm, F("blockterm"), F("config of block terminal"))
|
||||||
|
MAKE_PSTR_LIST(blockHyst, F("blockhyst"), F("hyst. for bolier block"))
|
||||||
|
MAKE_PSTR_LIST(releaseWait, F("releasewait"), F("boiler release wait time"))
|
||||||
|
|
||||||
// the following are dhw for the boiler and automatically tagged with 'ww'
|
// the following are dhw for the boiler and automatically tagged with 'ww'
|
||||||
MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("gewählte Temperatur"))
|
MAKE_PSTR_LIST(wWSelTemp, F("wwseltemp"), F("gewählte Temperatur"))
|
||||||
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
||||||
@@ -565,7 +614,9 @@ MAKE_PSTR_LIST(wWCharging, F("wwcharging"), F("Laden"))
|
|||||||
MAKE_PSTR_LIST(wWRecharging, F("wwrecharging"), F("Nachladen"))
|
MAKE_PSTR_LIST(wWRecharging, F("wwrecharging"), F("Nachladen"))
|
||||||
MAKE_PSTR_LIST(wWTempOK, F("wwtempok"), F("Temperatur ok"))
|
MAKE_PSTR_LIST(wWTempOK, F("wwtempok"), F("Temperatur ok"))
|
||||||
MAKE_PSTR_LIST(wWActive, F("wwactive"), F("aktiv"))
|
MAKE_PSTR_LIST(wWActive, F("wwactive"), F("aktiv"))
|
||||||
MAKE_PSTR_LIST(ww3wayValve, F("ww3wayvalve"), F("3way valve active"))
|
MAKE_PSTR_LIST(wwTempOK, F("wwtempok"), F("Temperatur ok"))
|
||||||
|
MAKE_PSTR_LIST(wwActive, F("wwactive"), F("aktiv"))
|
||||||
|
MAKE_PSTR_LIST(ww3wayValve, F("ww3wayvalve"), F("3-Wegeventil aktiv"))
|
||||||
MAKE_PSTR_LIST(wWSetPumpPower, F("wwsetpumppower"), F("Soll Pumpenleistung"))
|
MAKE_PSTR_LIST(wWSetPumpPower, F("wwsetpumppower"), F("Soll Pumpenleistung"))
|
||||||
MAKE_PSTR_LIST(mixerTemp, F("mixertemp"), F("Mischertemperatur"))
|
MAKE_PSTR_LIST(mixerTemp, F("mixertemp"), F("Mischertemperatur"))
|
||||||
MAKE_PSTR_LIST(wwCylMiddleTemp, F("wwcylmiddletemp"), F("cylinder middle temperature (TS3)"))
|
MAKE_PSTR_LIST(wwCylMiddleTemp, F("wwcylmiddletemp"), F("cylinder middle temperature (TS3)"))
|
||||||
@@ -580,11 +631,11 @@ MAKE_PSTR_LIST(wwMaxTemp, F("wwmaxtemp"), F("Maximale Temperatur"))
|
|||||||
MAKE_PSTR_LIST(wwOneTimeKey, F("wwonetimekey"), F("Einmalladungstaste"))
|
MAKE_PSTR_LIST(wwOneTimeKey, F("wwonetimekey"), F("Einmalladungstaste"))
|
||||||
|
|
||||||
// mqtt values / commands
|
// mqtt values / commands
|
||||||
MAKE_PSTR_LIST(switchtime, F("switchtime"), F("program switchtime"))
|
MAKE_PSTR_LIST(switchtime, F("switchtime"), F("Program Schaltzeit"))
|
||||||
MAKE_PSTR_LIST(switchtime1, F("switchtime1"), F("own1 program switchtime"))
|
MAKE_PSTR_LIST(switchtime1, F("switchtime1"), F("Program 1 Schaltzeit"))
|
||||||
MAKE_PSTR_LIST(switchtime2, F("switchtime2"), F("own2 program switchtime"))
|
MAKE_PSTR_LIST(switchtime2, F("switchtime2"), F("Programm 2 Schaltzeit"))
|
||||||
MAKE_PSTR_LIST(wwswitchtime, F("wwswitchtime"), F("program switchtime"))
|
MAKE_PSTR_LIST(wwswitchtime, F("wwswitchtime"), F("Programm Schaltzeit"))
|
||||||
MAKE_PSTR_LIST(wwcircswitchtime, F("wwcircswitchtime"), F("circulation program switchtime"))
|
MAKE_PSTR_LIST(wwcircswitchtime, F("wwcircswitchtime"), F("Zirculationsprogramm Schaltzeit"))
|
||||||
MAKE_PSTR_LIST(dateTime, F("datetime"), F("Datum/Zeit"))
|
MAKE_PSTR_LIST(dateTime, F("datetime"), F("Datum/Zeit"))
|
||||||
MAKE_PSTR_LIST(errorCode, F("errorcode"), F("Fehlermeldung"))
|
MAKE_PSTR_LIST(errorCode, F("errorcode"), F("Fehlermeldung"))
|
||||||
MAKE_PSTR_LIST(ibaMainDisplay, F("display"), F("Anzeige"))
|
MAKE_PSTR_LIST(ibaMainDisplay, F("display"), F("Anzeige"))
|
||||||
@@ -651,8 +702,11 @@ MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("berechnete Flusstemperatu
|
|||||||
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("Heizungstyp"))
|
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("Heizungstyp"))
|
||||||
MAKE_PSTR_LIST(summersetmode, F("summersetmode"), F("Einstellung Sommerbetrieb"))
|
MAKE_PSTR_LIST(summersetmode, F("summersetmode"), F("Einstellung Sommerbetrieb"))
|
||||||
MAKE_PSTR_LIST(hpoperatingmode, F("hpoperatingmode"), F("Wärmepumpe Betriebsmodus"))
|
MAKE_PSTR_LIST(hpoperatingmode, F("hpoperatingmode"), F("Wärmepumpe Betriebsmodus"))
|
||||||
|
MAKE_PSTR_LIST(hpoperatingstate, F("hpoperatingstate"), F("heatpump operating state"))
|
||||||
MAKE_PSTR_LIST(controlmode, F("controlmode"), F("Kontrollmodus"))
|
MAKE_PSTR_LIST(controlmode, F("controlmode"), F("Kontrollmodus"))
|
||||||
MAKE_PSTR_LIST(control, F("control"), F("Fernsteuerung"))
|
MAKE_PSTR_LIST(control, F("control"), F("Fernsteuerung"))
|
||||||
|
MAKE_PSTR_LIST(wwHolidays, F("wwholidays"), F("holiday dates"))
|
||||||
|
MAKE_PSTR_LIST(wwVacations, F("wwvacations"), F("vacation dates"))
|
||||||
MAKE_PSTR_LIST(holidays, F("holidays"), F("holiday dates"))
|
MAKE_PSTR_LIST(holidays, F("holidays"), F("holiday dates"))
|
||||||
MAKE_PSTR_LIST(vacations, F("vacations"), F("vacation dates"))
|
MAKE_PSTR_LIST(vacations, F("vacations"), F("vacation dates"))
|
||||||
MAKE_PSTR_LIST(program, F("program"), F("Programm"))
|
MAKE_PSTR_LIST(program, F("program"), F("Programm"))
|
||||||
@@ -669,9 +723,11 @@ MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("Absenkmodus unter Temperatur"))
|
|||||||
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("Urlaub Absenkmodus unter Temperatur"))
|
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("Urlaub Absenkmodus unter Temperatur"))
|
||||||
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("Urlaub Absenkmodus"))
|
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("Urlaub Absenkmodus"))
|
||||||
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("Frostschutz Modus"))
|
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("Frostschutz Modus"))
|
||||||
|
MAKE_PSTR_LIST(nofrostmode1, F("nofrostmode1"), F("nofrost mode")) // RC310
|
||||||
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("Raumtemperatur der Fernsteuerung"))
|
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("Raumtemperatur der Fernsteuerung"))
|
||||||
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
||||||
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
||||||
|
MAKE_PSTR_LIST(switchonoptimization, F("switchonoptimization"), F("switch-on optimization"))
|
||||||
|
|
||||||
// heatpump
|
// heatpump
|
||||||
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative Luftfeuchte"))
|
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative Luftfeuchte"))
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ MAKE_PSTR_WORD(reconnect)
|
|||||||
MAKE_PSTR_WORD(ssid)
|
MAKE_PSTR_WORD(ssid)
|
||||||
MAKE_PSTR_WORD(heartbeat)
|
MAKE_PSTR_WORD(heartbeat)
|
||||||
MAKE_PSTR_WORD(users)
|
MAKE_PSTR_WORD(users)
|
||||||
MAKE_PSTR_WORD(master)
|
|
||||||
MAKE_PSTR_WORD(pin)
|
|
||||||
MAKE_PSTR_WORD(publish)
|
MAKE_PSTR_WORD(publish)
|
||||||
MAKE_PSTR_WORD(timeout)
|
MAKE_PSTR_WORD(timeout)
|
||||||
MAKE_PSTR_WORD(board_profile)
|
MAKE_PSTR_WORD(board_profile)
|
||||||
@@ -105,7 +103,6 @@ MAKE_PSTR_WORD(unknown)
|
|||||||
MAKE_PSTR_WORD(dallassensor)
|
MAKE_PSTR_WORD(dallassensor)
|
||||||
|
|
||||||
// format strings
|
// format strings
|
||||||
MAKE_PSTR(master_thermostat_fmt, "Master Thermostat device ID: %s")
|
|
||||||
MAKE_PSTR(host_fmt, "Host: %s")
|
MAKE_PSTR(host_fmt, "Host: %s")
|
||||||
MAKE_PSTR(port_fmt, "Port: %d")
|
MAKE_PSTR(port_fmt, "Port: %d")
|
||||||
MAKE_PSTR(hostname_fmt, "Hostname: %s")
|
MAKE_PSTR(hostname_fmt, "Hostname: %s")
|
||||||
@@ -206,9 +203,9 @@ MAKE_PSTR(l, "l")
|
|||||||
// mqtt tags must not have spaces
|
// mqtt tags must not have spaces
|
||||||
MAKE_PSTR(tag_none, "")
|
MAKE_PSTR(tag_none, "")
|
||||||
MAKE_PSTR(tag_heartbeat, "")
|
MAKE_PSTR(tag_heartbeat, "")
|
||||||
MAKE_PSTR(tag_boiler_data, "")
|
MAKE_PSTR(tag_boiler_data_ww, "dhw")
|
||||||
|
MAKE_PSTR(tag_device_data, "")
|
||||||
MAKE_PSTR(tag_device_data_ww, "dhw")
|
MAKE_PSTR(tag_device_data_ww, "dhw")
|
||||||
MAKE_PSTR(tag_thermostat_data, "")
|
|
||||||
MAKE_PSTR(tag_hc1, "hc1")
|
MAKE_PSTR(tag_hc1, "hc1")
|
||||||
MAKE_PSTR(tag_hc2, "hc2")
|
MAKE_PSTR(tag_hc2, "hc2")
|
||||||
MAKE_PSTR(tag_hc3, "hc3")
|
MAKE_PSTR(tag_hc3, "hc3")
|
||||||
@@ -227,6 +224,7 @@ MAKE_PSTR(tag_wwc7, "wwc7")
|
|||||||
MAKE_PSTR(tag_wwc8, "wwc8")
|
MAKE_PSTR(tag_wwc8, "wwc8")
|
||||||
MAKE_PSTR(tag_wwc9, "wwc9")
|
MAKE_PSTR(tag_wwc9, "wwc9")
|
||||||
MAKE_PSTR(tag_wwc10, "wwc10")
|
MAKE_PSTR(tag_wwc10, "wwc10")
|
||||||
|
MAKE_PSTR(tag_ahs, "ahs")
|
||||||
MAKE_PSTR(tag_hs1, "hs1")
|
MAKE_PSTR(tag_hs1, "hs1")
|
||||||
MAKE_PSTR(tag_hs2, "hs2")
|
MAKE_PSTR(tag_hs2, "hs2")
|
||||||
MAKE_PSTR(tag_hs3, "hs3")
|
MAKE_PSTR(tag_hs3, "hs3")
|
||||||
@@ -246,8 +244,9 @@ MAKE_PSTR(tag_hs16, "hs16")
|
|||||||
|
|
||||||
// MQTT topic names
|
// MQTT topic names
|
||||||
// MAKE_PSTR(tag_heartbeat_mqtt, "heartbeat")
|
// MAKE_PSTR(tag_heartbeat_mqtt, "heartbeat")
|
||||||
MAKE_PSTR(tag_boiler_data_mqtt, "")
|
// MAKE_PSTR(tag_boiler_data_mqtt, "")
|
||||||
MAKE_PSTR(tag_device_data_ww_mqtt, "ww")
|
MAKE_PSTR(tag_boiler_data_ww_mqtt, "ww")
|
||||||
|
MAKE_PSTR(tag_device_data_ww_mqtt, "")
|
||||||
|
|
||||||
// boiler
|
// boiler
|
||||||
MAKE_PSTR_WORD(time)
|
MAKE_PSTR_WORD(time)
|
||||||
@@ -271,6 +270,8 @@ MAKE_PSTR_WORD(buffer)
|
|||||||
MAKE_PSTR(bufferedflow, "buffered flow")
|
MAKE_PSTR(bufferedflow, "buffered flow")
|
||||||
MAKE_PSTR(layeredbuffer, "layered buffer")
|
MAKE_PSTR(layeredbuffer, "layered buffer")
|
||||||
MAKE_PSTR_WORD(maintenance)
|
MAKE_PSTR_WORD(maintenance)
|
||||||
|
MAKE_PSTR_WORD(heating)
|
||||||
|
MAKE_PSTR_WORD(cooling)
|
||||||
|
|
||||||
// boiler lists
|
// boiler lists
|
||||||
MAKE_PSTR_LIST(tpl_date, F("Format: < dd.mm.yyyy >")) // template for text input
|
MAKE_PSTR_LIST(tpl_date, F("Format: < dd.mm.yyyy >")) // template for text input
|
||||||
@@ -283,8 +284,16 @@ MAKE_PSTR_LIST(enum_flow, F_(off), F_(flow), F_(bufferedflow), F_(buffer), F_(la
|
|||||||
MAKE_PSTR_LIST(enum_reset, F("-"), F_(maintenance), F_(error))
|
MAKE_PSTR_LIST(enum_reset, F("-"), F_(maintenance), F_(error))
|
||||||
// MAKE_PSTR_LIST(enum_bool, F_(off), F_(on))
|
// MAKE_PSTR_LIST(enum_bool, F_(off), F_(on))
|
||||||
|
|
||||||
|
// AM200 lists
|
||||||
|
MAKE_PSTR_LIST(enum_vr2Config, F_(off), F("bypass"));
|
||||||
|
MAKE_PSTR_LIST(enum_aPumpSignal, F_(off), F("pwm"), F("pwm_invers"));
|
||||||
|
MAKE_PSTR_LIST(enum_bufBypass, F("no"), F_(mixer), F("valve"));
|
||||||
|
MAKE_PSTR_LIST(enum_bufConfig, F("monovalent"), F("bivalent"));
|
||||||
|
MAKE_PSTR_LIST(enum_blockMode, F_(off), F_(auto), F("blocking"));
|
||||||
|
MAKE_PSTR_LIST(enum_blockTerm, F("n_o"), F("n_c"));
|
||||||
|
|
||||||
//heatpump
|
//heatpump
|
||||||
MAKE_PSTR_LIST(enum_hpactivity, F("none"), F("heating"), F("cooling"), F("hot water"), F("pool"))
|
MAKE_PSTR_LIST(enum_hpactivity, F("none"), F_(heating), F_(cooling), F("hot_water"), F("pool"))
|
||||||
|
|
||||||
// mixer
|
// mixer
|
||||||
MAKE_PSTR_LIST(enum_shunt, F("stopped"), F("opening"), F("closing"), F("open"), F("close"))
|
MAKE_PSTR_LIST(enum_shunt, F("stopped"), F("opening"), F("closing"), F("open"), F("close"))
|
||||||
@@ -313,6 +322,7 @@ MAKE_PSTR_WORD(winter)
|
|||||||
MAKE_PSTR_WORD(outdoor)
|
MAKE_PSTR_WORD(outdoor)
|
||||||
MAKE_PSTR_WORD(mpc)
|
MAKE_PSTR_WORD(mpc)
|
||||||
MAKE_PSTR_WORD(room)
|
MAKE_PSTR_WORD(room)
|
||||||
|
MAKE_PSTR_WORD(room_outdoor)
|
||||||
MAKE_PSTR_WORD(power)
|
MAKE_PSTR_WORD(power)
|
||||||
MAKE_PSTR_WORD(constant)
|
MAKE_PSTR_WORD(constant)
|
||||||
MAKE_PSTR_WORD(simple)
|
MAKE_PSTR_WORD(simple)
|
||||||
@@ -341,7 +351,7 @@ MAKE_PSTR(functioning_mode, "functioning mode")
|
|||||||
MAKE_PSTR(smoke_temperature, "smoke temperature")
|
MAKE_PSTR(smoke_temperature, "smoke temperature")
|
||||||
|
|
||||||
// thermostat lists
|
// thermostat lists
|
||||||
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | dd.mm.yyyy-hh:mm:ss-dw-dst >"))
|
MAKE_PSTR_LIST(tpl_datetime, F("Format: < NTP | dd.mm.yyyy-hh:mm:ss-day(0-6)-dst(0/1) >"))
|
||||||
MAKE_PSTR_LIST(tpl_switchtime, F("Format: <nn> [ not_set | day hh:mm on|off ]"))
|
MAKE_PSTR_LIST(tpl_switchtime, F("Format: <nn> [ not_set | day hh:mm on|off ]"))
|
||||||
MAKE_PSTR_LIST(tpl_switchtime1, F("Format: <nn> [ not_set | day hh:mm Tn ]"))
|
MAKE_PSTR_LIST(tpl_switchtime1, F("Format: <nn> [ not_set | day hh:mm Tn ]"))
|
||||||
MAKE_PSTR_LIST(tpl_holidays, F("format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
MAKE_PSTR_LIST(tpl_holidays, F("format: < dd.mm.yyyy-dd.mm.yyyy >"))
|
||||||
@@ -360,14 +370,15 @@ MAKE_PSTR_LIST(enum_ibaLanguage_RC30, F_(german), F_(dutch))
|
|||||||
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
MAKE_PSTR_LIST(enum_floordrystatus, F_(off), F_(start), F_(heat), F_(hold), F_(cool), F_(end))
|
||||||
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy))
|
MAKE_PSTR_LIST(enum_ibaBuildingType, F_(light), F_(medium), F_(heavy))
|
||||||
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
MAKE_PSTR_LIST(enum_PID, F("fast"), F_(medium), F("slow"))
|
||||||
MAKE_PSTR_LIST(enum_wwMode, F_(off), F_(low), F_(high), F_(auto), F_(own_prog))
|
MAKE_PSTR_LIST(enum_wwMode, F_(off), F("normal"), F_(comfort), F_(auto), F_(own_prog), F_(eco))
|
||||||
MAKE_PSTR_LIST(enum_wwCircMode, F_(off), F_(on), F_(auto), F_(own_prog))
|
MAKE_PSTR_LIST(enum_wwCircMode, F_(off), F_(on), F_(auto), F_(own_prog))
|
||||||
MAKE_PSTR_LIST(enum_wwMode2, F_(off), F_(on), F_(auto))
|
MAKE_PSTR_LIST(enum_wwMode2, F_(off), F_(on), F_(auto))
|
||||||
MAKE_PSTR_LIST(enum_wwMode3, F_(on), F_(off), F_(auto))
|
MAKE_PSTR_LIST(enum_wwMode3, F_(on), F_(off), F_(auto))
|
||||||
MAKE_PSTR_LIST(enum_heatingtype, F_(off), F_(radiator), F_(convector), F_(floor))
|
MAKE_PSTR_LIST(enum_heatingtype, F_(off), F_(radiator), F_(convector), F_(floor))
|
||||||
MAKE_PSTR_LIST(enum_summermode, F_(summer), F_(auto), F_(winter))
|
MAKE_PSTR_LIST(enum_summermode, F_(summer), F_(auto), F_(winter))
|
||||||
MAKE_PSTR_LIST(enum_hpoperatingmode, F_(off), F_(auto), F("heating"), F("cooling"))
|
MAKE_PSTR_LIST(enum_hpoperatingmode, F_(off), F_(auto), F_(heating), F_(cooling))
|
||||||
MAKE_PSTR_LIST(enum_summer, F_(winter), F_(summer))
|
MAKE_PSTR_LIST(enum_summer, F_(winter), F_(summer))
|
||||||
|
MAKE_PSTR_LIST(enum_operatingstate, F_(heating), F_(off), F_(cooling))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_mode, F_(manual), F_(auto)) // RC100, RC300, RC310
|
MAKE_PSTR_LIST(enum_mode, F_(manual), F_(auto)) // RC100, RC300, RC310
|
||||||
MAKE_PSTR_LIST(enum_mode2, F_(off), F_(manual), F_(auto)) // RC20
|
MAKE_PSTR_LIST(enum_mode2, F_(off), F_(manual), F_(auto)) // RC20
|
||||||
@@ -383,9 +394,12 @@ MAKE_PSTR_LIST(enum_modetype4, F_(nofrost), F_(eco), F_(heat))
|
|||||||
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
MAKE_PSTR_LIST(enum_modetype5, F_(off), F_(on))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_reducemode, F_(nofrost), F_(reduce), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_reducemode1, F_(outdoor), F_(room), F_(reduce)) // RC310 values: 1-3
|
||||||
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
MAKE_PSTR_LIST(enum_nofrostmode, F_(off), F_(room), F_(outdoor))
|
||||||
|
MAKE_PSTR_LIST(enum_nofrostmode1, F_(room), F_(outdoor), F_(room_outdoor))
|
||||||
|
|
||||||
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
MAKE_PSTR_LIST(enum_controlmode, F_(off), F_(optimized), F_(simple), F_(mpc), F_(room), F_(power), F_(constant))
|
||||||
|
MAKE_PSTR_LIST(enum_controlmode1, F("weather-compensated"), F("outside-basepoint"), F("n/a"), F_(room)) // RC310 1-4
|
||||||
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
MAKE_PSTR_LIST(enum_controlmode2, F_(outdoor), F_(room))
|
||||||
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
|
// MAKE_PSTR_LIST(enum_controlmode3, F_(off), F_(room), F_(outdoor), F("room+outdoor"))
|
||||||
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
|
MAKE_PSTR_LIST(enum_control, F_(off), F_(rc20), F_(rc3x))
|
||||||
@@ -531,6 +545,37 @@ MAKE_PSTR_LIST(electricFactor, F("electricfactor"), F("electric energy factor"))
|
|||||||
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
MAKE_PSTR_LIST(delayBoiler, F("delayboiler"), F("delay boiler support"))
|
||||||
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
MAKE_PSTR_LIST(tempDiffBoiler, F("tempdiffboiler"), F("tempediff boiler support"))
|
||||||
|
|
||||||
|
// alternative heatsource AM200
|
||||||
|
MAKE_PSTR_LIST(aCylTopTemp, F("cyltoptemp"), F("cylinder top temperature"))
|
||||||
|
MAKE_PSTR_LIST(aCylCenterTemp, F("cylcentertemp"), F("cylinder center temperature"))
|
||||||
|
MAKE_PSTR_LIST(aCylBottomTemp, F("cylbottomtemp"), F("cylinder bottom temperature"))
|
||||||
|
MAKE_PSTR_LIST(aFlowTemp, F("altflowtemp"), F("alternative hs flow temperature"))
|
||||||
|
MAKE_PSTR_LIST(aRetTemp, F("altrettemp"), F("alternative hs return temperature"))
|
||||||
|
MAKE_PSTR_LIST(sysFlowTemp, F("sysflowtemp"), F("system flow temperature"))
|
||||||
|
MAKE_PSTR_LIST(sysRetTemp, F("sysrettemp"), F("system return temperature"))
|
||||||
|
MAKE_PSTR_LIST(valveByPass, F("valvebypass"), F("bypass valve"))
|
||||||
|
MAKE_PSTR_LIST(valveBuffer, F("valvebuffer"), F("buffer valve"))
|
||||||
|
MAKE_PSTR_LIST(valveReturn, F("valvereturn"), F("return valve"))
|
||||||
|
MAKE_PSTR_LIST(aPumpMod, F("altpumpmod"), F("alternative hs pump modulation"))
|
||||||
|
MAKE_PSTR_LIST(heatSource, F("heatsource"), F("alternative heating active"))
|
||||||
|
|
||||||
|
MAKE_PSTR_LIST(vr2Config, F("vr2config"), F("vr2 configuration"))
|
||||||
|
MAKE_PSTR_LIST(ahsActivated, F("ahsactivated"), F("alternate heat source activation"))
|
||||||
|
MAKE_PSTR_LIST(aPumpConfig, F("apumpconfig"), F("primary pump config"))
|
||||||
|
MAKE_PSTR_LIST(aPumpSignal, F("apumpsignal"), F("output for pr1 pump"))
|
||||||
|
MAKE_PSTR_LIST(aPumpMin, F("apumpmin"), F("min output pump pr1"))
|
||||||
|
MAKE_PSTR_LIST(tempRise, F("temprise"), F("ahs return temp rise"))
|
||||||
|
MAKE_PSTR_LIST(setReturnTemp, F("setreturntemp"), F("set temp return"))
|
||||||
|
MAKE_PSTR_LIST(mixRuntime, F("mixruntime"), F("mixer run time"))
|
||||||
|
// MAKE_PSTR_LIST(setFlowTemp, F("setflowtemp"), F("set flow temp"))
|
||||||
|
MAKE_PSTR_LIST(bufBypass, F("bufbypass"), F("buffer bypass config"))
|
||||||
|
MAKE_PSTR_LIST(bufMixRuntime, F("bufmixruntime"), F("bypass mixer run time"))
|
||||||
|
MAKE_PSTR_LIST(bufConfig, F("bufconfig"), F("dhw buffer config"))
|
||||||
|
MAKE_PSTR_LIST(blockMode, F("blockmode"), F("config htg. blocking mode"))
|
||||||
|
MAKE_PSTR_LIST(blockTerm, F("blockterm"), F("config of block terminal"))
|
||||||
|
MAKE_PSTR_LIST(blockHyst, F("blockhyst"), F("hyst. for bolier block"))
|
||||||
|
MAKE_PSTR_LIST(releaseWait, F("releasewait"), F("boiler release wait time"))
|
||||||
|
|
||||||
// the following are dhw for the boiler and automatically tagged with 'ww'
|
// the following are dhw for the boiler and automatically tagged with 'ww'
|
||||||
MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature"))
|
MAKE_PSTR_LIST(wwSelTemp, F("wwseltemp"), F("selected temperature"))
|
||||||
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
MAKE_PSTR_LIST(wwSelTempLow, F("wwseltemplow"), F("selected lower temperature"))
|
||||||
@@ -632,6 +677,7 @@ MAKE_PSTR_LIST(nighttemp2, F("nighttemp"), F("night temperature T1"))
|
|||||||
MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco temperature"))
|
MAKE_PSTR_LIST(ecotemp, F("ecotemp"), F("eco temperature"))
|
||||||
MAKE_PSTR_LIST(manualtemp, F("manualtemp"), F("manual temperature"))
|
MAKE_PSTR_LIST(manualtemp, F("manualtemp"), F("manual temperature"))
|
||||||
MAKE_PSTR_LIST(tempautotemp, F("tempautotemp"), F("temporary set temperature automode"))
|
MAKE_PSTR_LIST(tempautotemp, F("tempautotemp"), F("temporary set temperature automode"))
|
||||||
|
MAKE_PSTR_LIST(remoteseltemp, F("remoteseltemp"), F("temporary set temperature from remote"))
|
||||||
MAKE_PSTR_LIST(comforttemp, F("comforttemp"), F("comfort temperature"))
|
MAKE_PSTR_LIST(comforttemp, F("comforttemp"), F("comfort temperature"))
|
||||||
MAKE_PSTR_LIST(summertemp, F("summertemp"), F("summer temperature"))
|
MAKE_PSTR_LIST(summertemp, F("summertemp"), F("summer temperature"))
|
||||||
MAKE_PSTR_LIST(designtemp, F("designtemp"), F("design temperature"))
|
MAKE_PSTR_LIST(designtemp, F("designtemp"), F("design temperature"))
|
||||||
@@ -646,8 +692,11 @@ MAKE_PSTR_LIST(targetflowtemp, F("targetflowtemp"), F("target flow temperature")
|
|||||||
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("heating type"))
|
MAKE_PSTR_LIST(heatingtype, F("heatingtype"), F("heating type"))
|
||||||
MAKE_PSTR_LIST(summersetmode, F("summersetmode"), F("set summer mode"))
|
MAKE_PSTR_LIST(summersetmode, F("summersetmode"), F("set summer mode"))
|
||||||
MAKE_PSTR_LIST(hpoperatingmode, F("hpoperatingmode"), F("heatpump operating mode"))
|
MAKE_PSTR_LIST(hpoperatingmode, F("hpoperatingmode"), F("heatpump operating mode"))
|
||||||
|
MAKE_PSTR_LIST(hpoperatingstate, F("hpoperatingstate"), F("heatpump operating state"))
|
||||||
MAKE_PSTR_LIST(controlmode, F("controlmode"), F("control mode"))
|
MAKE_PSTR_LIST(controlmode, F("controlmode"), F("control mode"))
|
||||||
MAKE_PSTR_LIST(control, F("control"), F("control device"))
|
MAKE_PSTR_LIST(control, F("control"), F("control device"))
|
||||||
|
MAKE_PSTR_LIST(wwHolidays, F("wwholidays"), F("holiday dates"))
|
||||||
|
MAKE_PSTR_LIST(wwVacations, F("wwvacations"), F("vacation dates"))
|
||||||
MAKE_PSTR_LIST(holidays, F("holidays"), F("holiday dates"))
|
MAKE_PSTR_LIST(holidays, F("holidays"), F("holiday dates"))
|
||||||
MAKE_PSTR_LIST(vacations, F("vacations"), F("vacation dates"))
|
MAKE_PSTR_LIST(vacations, F("vacations"), F("vacation dates"))
|
||||||
MAKE_PSTR_LIST(program, F("program"), F("program"))
|
MAKE_PSTR_LIST(program, F("program"), F("program"))
|
||||||
@@ -664,9 +713,11 @@ MAKE_PSTR_LIST(reducetemp, F("reducetemp"), F("off/reduce switch temperature"))
|
|||||||
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature"))
|
MAKE_PSTR_LIST(vacreducetemp, F("vacreducetemp"), F("vacations off/reduce switch temperature"))
|
||||||
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode"))
|
MAKE_PSTR_LIST(vacreducemode, F("vacreducemode"), F("vacations reduce mode"))
|
||||||
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode"))
|
MAKE_PSTR_LIST(nofrostmode, F("nofrostmode"), F("nofrost mode"))
|
||||||
|
MAKE_PSTR_LIST(nofrostmode1, F("nofrostmode1"), F("nofrost mode")) // RC310
|
||||||
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
|
MAKE_PSTR_LIST(remotetemp, F("remotetemp"), F("room temperature from remote"))
|
||||||
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
MAKE_PSTR_LIST(reducehours, F("reducehours"), F("duration for nighttemp"))
|
||||||
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
MAKE_PSTR_LIST(reduceminutes, F("reduceminutes"), F("remaining time for nightmode"))
|
||||||
|
MAKE_PSTR_LIST(switchonoptimization, F("switchonoptimization"), F("switch-on optimization"))
|
||||||
|
|
||||||
// heatpump
|
// heatpump
|
||||||
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity"))
|
MAKE_PSTR_LIST(airHumidity, F("airhumidity"), F("relative air humidity"))
|
||||||
|
|||||||
63
src/mqtt.cpp
63
src/mqtt.cpp
@@ -445,19 +445,17 @@ void Mqtt::start() {
|
|||||||
}
|
}
|
||||||
connecting_ = false;
|
connecting_ = false;
|
||||||
if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
|
if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
|
||||||
LOG_INFO(F("MQTT disconnected: TCP"));
|
LOG_WARNING(F("MQTT disconnected: TCP"));
|
||||||
}
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
|
||||||
if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
|
LOG_WARNING(F("MQTT disconnected: Identifier Rejected"));
|
||||||
LOG_INFO(F("MQTT disconnected: Identifier Rejected"));
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE) {
|
||||||
}
|
LOG_WARNING(F("MQTT disconnected: Server unavailable"));
|
||||||
if (reason == AsyncMqttClientDisconnectReason::MQTT_SERVER_UNAVAILABLE) {
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS) {
|
||||||
LOG_INFO(F("MQTT disconnected: Server unavailable"));
|
LOG_WARNING(F("MQTT disconnected: Malformed credentials"));
|
||||||
}
|
} else if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) {
|
||||||
if (reason == AsyncMqttClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS) {
|
LOG_WARNING(F("MQTT disconnected: Not authorized"));
|
||||||
LOG_INFO(F("MQTT disconnected: Malformed credentials"));
|
} else {
|
||||||
}
|
LOG_WARNING(F("MQTT disconnected: code %d"), reason);
|
||||||
if (reason == AsyncMqttClientDisconnectReason::MQTT_NOT_AUTHORIZED) {
|
|
||||||
LOG_INFO(F("MQTT disconnected: Not authorized"));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -628,10 +626,11 @@ void Mqtt::ha_status() {
|
|||||||
doc["~"] = mqtt_base_; // default ems-esp
|
doc["~"] = mqtt_base_; // default ems-esp
|
||||||
// doc["avty_t"] = FJSON("~/status"); // commented out, as it causes errors in HA sometimes
|
// doc["avty_t"] = FJSON("~/status"); // commented out, as it causes errors in HA sometimes
|
||||||
// doc["json_attr_t"] = FJSON("~/heartbeat"); // store also as HA attributes
|
// doc["json_attr_t"] = FJSON("~/heartbeat"); // store also as HA attributes
|
||||||
doc["stat_t"] = FJSON("~/heartbeat");
|
doc["stat_t"] = FJSON("~/heartbeat");
|
||||||
doc["name"] = FJSON("EMS-ESP status");
|
doc["object_id"] = FJSON("ems_esp_status");
|
||||||
doc["ic"] = F_(icondevice);
|
doc["name"] = FJSON("EMS-ESP status");
|
||||||
doc["val_tpl"] = FJSON("{{value_json['bus_status']}}");
|
doc["ic"] = F_(icondevice);
|
||||||
|
doc["val_tpl"] = FJSON("{{value_json['bus_status']}}");
|
||||||
|
|
||||||
JsonObject dev = doc.createNestedObject("dev");
|
JsonObject dev = doc.createNestedObject("dev");
|
||||||
dev["name"] = F_(EMSESP); // "EMS-ESP"
|
dev["name"] = F_(EMSESP); // "EMS-ESP"
|
||||||
@@ -1104,15 +1103,23 @@ void Mqtt::publish_ha_sensor_config(uint8_t type,
|
|||||||
snprintf(stat_t, sizeof(stat_t), "~/%s", tag_to_topic(device_type, tag).c_str());
|
snprintf(stat_t, sizeof(stat_t), "~/%s", tag_to_topic(device_type, tag).c_str());
|
||||||
doc["stat_t"] = stat_t;
|
doc["stat_t"] = stat_t;
|
||||||
|
|
||||||
// name = <device> <tag> <name>
|
// friendly name = <tag> <name>
|
||||||
char new_name[80];
|
char short_name[70];
|
||||||
if (have_tag) {
|
if (have_tag) {
|
||||||
snprintf(new_name, sizeof(new_name), "%s %s %s", device_name, EMSdevice::tag_to_string(tag).c_str(), read_flash_string(name).c_str());
|
snprintf(short_name, sizeof(short_name), "%s %s", EMSdevice::tag_to_string(tag).c_str(), read_flash_string(name).c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(new_name, sizeof(new_name), "%s %s", device_name, read_flash_string(name).c_str());
|
snprintf(short_name, sizeof(short_name), "%s", read_flash_string(name).c_str());
|
||||||
}
|
}
|
||||||
new_name[0] = toupper(new_name[0]); // capitalize first letter
|
|
||||||
doc["name"] = new_name;
|
// entity id = emsesp_<device>_<tag>_<name>
|
||||||
|
char long_name[130];
|
||||||
|
snprintf(long_name, sizeof(long_name), "%s_%s", device_name, short_name);
|
||||||
|
// snprintf(long_name, sizeof(long_name), "emsesp_%s_%s", device_name, short_name); //wouldn't it be better?
|
||||||
|
doc["object_id"] = long_name;
|
||||||
|
|
||||||
|
// name (friendly name) = <tag> <name>
|
||||||
|
short_name[0] = toupper(short_name[0]); // capitalize first letter
|
||||||
|
doc["name"] = short_name;
|
||||||
|
|
||||||
// value template
|
// value template
|
||||||
// if its nested mqtt format then use the appended entity name, otherwise take the original
|
// if its nested mqtt format then use the appended entity name, otherwise take the original
|
||||||
@@ -1240,7 +1247,8 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
|
|||||||
char seltemp_s[30];
|
char seltemp_s[30];
|
||||||
char currtemp_s[30];
|
char currtemp_s[30];
|
||||||
char mode_str_tpl[400];
|
char mode_str_tpl[400];
|
||||||
char name_s[30];
|
char name_s[10];
|
||||||
|
char id_s[20];
|
||||||
char uniq_id_s[30];
|
char uniq_id_s[30];
|
||||||
char temp_cmd_s[30];
|
char temp_cmd_s[30];
|
||||||
char mode_cmd_s[30];
|
char mode_cmd_s[30];
|
||||||
@@ -1279,7 +1287,8 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
|
|||||||
hc_mode_s,
|
hc_mode_s,
|
||||||
hc_mode_s);
|
hc_mode_s);
|
||||||
|
|
||||||
snprintf(name_s, sizeof(name_s), "Thermostat hc%d", hc_num);
|
snprintf(id_s, sizeof(id_s), "thermostat_hc%d", hc_num);
|
||||||
|
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
|
||||||
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num);
|
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num);
|
||||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
||||||
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
||||||
@@ -1287,6 +1296,7 @@ void Mqtt::publish_ha_climate_config(uint8_t tag, bool has_roomtemp, bool remove
|
|||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
||||||
|
|
||||||
doc["~"] = base();
|
doc["~"] = base();
|
||||||
|
doc["object_id"] = id_s;
|
||||||
doc["name"] = name_s;
|
doc["name"] = name_s;
|
||||||
doc["uniq_id"] = uniq_id_s;
|
doc["uniq_id"] = uniq_id_s;
|
||||||
doc["mode_stat_t"] = topic_t;
|
doc["mode_stat_t"] = topic_t;
|
||||||
@@ -1329,8 +1339,7 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if there is a tag add it
|
// if there is a tag add it
|
||||||
if (!EMSdevice::tag_to_mqtt(tag).empty()
|
if (!EMSdevice::tag_to_mqtt(tag).empty() && ((tag == DeviceValueTAG::TAG_BOILER_DATA_WW) || (!is_nested() && tag >= DeviceValueTAG::TAG_HC1))) {
|
||||||
&& ((device_type == EMSdevice::DeviceType::BOILER && tag == DeviceValueTAG::TAG_DEVICE_DATA_WW) || (!is_nested() && tag >= DeviceValueTAG::TAG_HC1))) {
|
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
return EMSdevice::device_type_2_device_name(device_type) + "_data_" + EMSdevice::tag_to_mqtt(tag);
|
||||||
} else {
|
} else {
|
||||||
return EMSdevice::device_type_2_device_name(device_type) + "_data";
|
return EMSdevice::device_type_2_device_name(device_type) + "_data";
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ void Shower::loop() {
|
|||||||
// first check to see if hot water has been on long enough to be recognized as a Shower/Bath
|
// first check to see if hot water has been on long enough to be recognized as a Shower/Bath
|
||||||
if (!shower_state_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) {
|
if (!shower_state_ && (time_now - timer_start_) > SHOWER_MIN_DURATION) {
|
||||||
set_shower_state(true);
|
set_shower_state(true);
|
||||||
publish_shower_data();
|
|
||||||
LOG_DEBUG(F("[Shower] hot water still running, starting shower timer"));
|
LOG_DEBUG(F("[Shower] hot water still running, starting shower timer"));
|
||||||
}
|
}
|
||||||
// check if the shower has been on too long
|
// check if the shower has been on too long
|
||||||
@@ -78,7 +77,12 @@ void Shower::loop() {
|
|||||||
if ((timer_pause_ - timer_start_) > SHOWER_OFFSET_TIME) {
|
if ((timer_pause_ - timer_start_) > SHOWER_OFFSET_TIME) {
|
||||||
duration_ = (timer_pause_ - timer_start_ - SHOWER_OFFSET_TIME);
|
duration_ = (timer_pause_ - timer_start_ - SHOWER_OFFSET_TIME);
|
||||||
if (duration_ > SHOWER_MIN_DURATION) {
|
if (duration_ > SHOWER_MIN_DURATION) {
|
||||||
publish_shower_data();
|
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc;
|
||||||
|
|
||||||
|
char s[50];
|
||||||
|
snprintf(s, 50, "%d minutes and %d seconds", (uint8_t)(duration_ / 60000), (uint8_t)((duration_ / 1000) % 60));
|
||||||
|
doc["duration"] = s;
|
||||||
|
Mqtt::publish(F("shower_data"), doc.as<JsonObject>());
|
||||||
LOG_DEBUG(F("[Shower] finished with duration %d"), duration_);
|
LOG_DEBUG(F("[Shower] finished with duration %d"), duration_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,34 +124,6 @@ void Shower::shower_alert_start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish to the shower_data topic
|
|
||||||
// showing whether the shower timer and alert are enabled or disabled
|
|
||||||
// and the duration of the last shower
|
|
||||||
void Shower::publish_shower_data() const {
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> doc;
|
|
||||||
|
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
|
||||||
doc["shower_timer"] = shower_timer_;
|
|
||||||
doc["shower_alert"] = shower_alert_;
|
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
|
||||||
doc["shower_timer"] = shower_timer_ ? 1 : 0;
|
|
||||||
doc["shower_alert"] = shower_alert_ ? 1 : 0;
|
|
||||||
} else {
|
|
||||||
char result[10];
|
|
||||||
doc["shower_timer"] = Helpers::render_boolean(result, shower_timer_);
|
|
||||||
doc["shower_alert"] = Helpers::render_boolean(result, shower_alert_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// only publish shower duration if there is a value
|
|
||||||
if (duration_ > SHOWER_MIN_DURATION) {
|
|
||||||
char s[50];
|
|
||||||
snprintf(s, 50, "%d minutes and %d seconds", (uint8_t)(duration_ / 60000), (uint8_t)((duration_ / 1000) % 60));
|
|
||||||
doc["duration"] = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mqtt::publish(F("shower_data"), doc.as<JsonObject>());
|
|
||||||
}
|
|
||||||
|
|
||||||
// send status of shower to MQTT topic called shower_active - which is determined by the state parameter
|
// send status of shower to MQTT topic called shower_active - which is determined by the state parameter
|
||||||
// and creates the HA config topic if HA enabled
|
// and creates the HA config topic if HA enabled
|
||||||
// force is used by EMSESP::publish_all_loop()
|
// force is used by EMSESP::publish_all_loop()
|
||||||
|
|||||||
20
src/shower.h
20
src/shower.h
@@ -30,25 +30,6 @@ class Shower {
|
|||||||
|
|
||||||
void set_shower_state(bool state, bool force = false);
|
void set_shower_state(bool state, bool force = false);
|
||||||
|
|
||||||
/* unused header
|
|
||||||
*
|
|
||||||
bool shower_alert() const {
|
|
||||||
return shower_alert_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shower_alert(const bool shower_alert) {
|
|
||||||
shower_alert_ = shower_alert;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool shower_timer() const {
|
|
||||||
return shower_timer_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void shower_timer(const bool shower_timer) {
|
|
||||||
shower_timer_ = shower_timer;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|
||||||
@@ -56,7 +37,6 @@ class Shower {
|
|||||||
static constexpr uint32_t SHOWER_MIN_DURATION = 120000; // in ms. 2 minutes, before recognizing its a shower
|
static constexpr uint32_t SHOWER_MIN_DURATION = 120000; // in ms. 2 minutes, before recognizing its a shower
|
||||||
static constexpr uint32_t SHOWER_OFFSET_TIME = 5000; // in ms. 5 seconds grace time, to calibrate actual time under the shower
|
static constexpr uint32_t SHOWER_OFFSET_TIME = 5000; // in ms. 5 seconds grace time, to calibrate actual time under the shower
|
||||||
|
|
||||||
void publish_shower_data() const;
|
|
||||||
void shower_alert_start();
|
void shower_alert_start();
|
||||||
void shower_alert_stop();
|
void shower_alert_stop();
|
||||||
|
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ void System::format(uuid::console::Shell & shell) {
|
|||||||
EMSuart::stop();
|
EMSuart::stop();
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
LITTLEFS.format();
|
LittleFS.format();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
System::system_restart();
|
System::system_restart();
|
||||||
@@ -433,7 +433,7 @@ void System::button_OnVLongPress(PButton & b) {
|
|||||||
EMSESP::console_.loop();
|
EMSESP::console_.loop();
|
||||||
|
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
Test::listDir(LITTLEFS, FS_CONFIG_DIRECTORY, 3);
|
Test::listDir(LittleFS, FS_CONFIG_DIRECTORY, 3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EMSESP::esp8266React.factoryReset();
|
EMSESP::esp8266React.factoryReset();
|
||||||
@@ -895,7 +895,7 @@ bool System::check_upgrade() {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
// see if we have a temp file, if so try and read it
|
// see if we have a temp file, if so try and read it
|
||||||
File new_file = LITTLEFS.open(TEMP_FILENAME_PATH);
|
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||||
if (new_file) {
|
if (new_file) {
|
||||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(FS_BUFFER_SIZE);
|
DynamicJsonDocument jsonDocument = DynamicJsonDocument(FS_BUFFER_SIZE);
|
||||||
DeserializationError error = deserializeJson(jsonDocument, new_file);
|
DeserializationError error = deserializeJson(jsonDocument, new_file);
|
||||||
@@ -923,7 +923,7 @@ bool System::check_upgrade() {
|
|||||||
|
|
||||||
// close (just in case) and remove the temp file
|
// close (just in case) and remove the temp file
|
||||||
new_file.close();
|
new_file.close();
|
||||||
LITTLEFS.remove(TEMP_FILENAME_PATH);
|
LittleFS.remove(TEMP_FILENAME_PATH);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -938,9 +938,9 @@ bool System::command_commands(const char * value, const int8_t id, JsonObject &
|
|||||||
// convert settings file into json object
|
// convert settings file into json object
|
||||||
void System::extractSettings(const char * filename, const char * section, JsonObject & output) {
|
void System::extractSettings(const char * filename, const char * section, JsonObject & output) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
File settingsFile = LITTLEFS.open(filename);
|
File settingsFile = LittleFS.open(filename);
|
||||||
if (settingsFile) {
|
if (settingsFile) {
|
||||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_XLARGE_DYN);
|
DynamicJsonDocument jsonDocument = DynamicJsonDocument(FS_BUFFER_SIZE);
|
||||||
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
|
DeserializationError error = deserializeJson(jsonDocument, settingsFile);
|
||||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
||||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||||
@@ -959,7 +959,7 @@ bool System::saveSettings(const char * filename, const char * section, JsonObjec
|
|||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
JsonObject section_json = input[section];
|
JsonObject section_json = input[section];
|
||||||
if (section_json) {
|
if (section_json) {
|
||||||
File section_file = LITTLEFS.open(filename, "w");
|
File section_file = LittleFS.open(filename, "w");
|
||||||
if (section_file) {
|
if (section_file) {
|
||||||
LOG_INFO(F("Applying new %s settings"), section);
|
LOG_INFO(F("Applying new %s settings"), section);
|
||||||
serializeJson(section_json, section_file);
|
serializeJson(section_json, section_file);
|
||||||
|
|||||||
14
src/system.h
14
src/system.h
@@ -77,6 +77,20 @@ class System {
|
|||||||
bool heartbeat_json(JsonObject & output);
|
bool heartbeat_json(JsonObject & output);
|
||||||
void send_heartbeat();
|
void send_heartbeat();
|
||||||
|
|
||||||
|
bool syslog_enabled() {
|
||||||
|
return syslog_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
|
unsigned long syslog_count() {
|
||||||
|
return syslog_.message_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long syslog_fails() {
|
||||||
|
return syslog_.message_fails();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void led_init(bool refresh);
|
void led_init(bool refresh);
|
||||||
void network_init(bool refresh);
|
void network_init(bool refresh);
|
||||||
void button_init(bool refresh);
|
void button_init(bool refresh);
|
||||||
|
|||||||
@@ -221,9 +221,6 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we receive a hc2.. telegram from 0x19.. match it to master_thermostat if master is 0x18
|
|
||||||
src = EMSESP::check_master_device(src, type_id, true);
|
|
||||||
|
|
||||||
// create the telegram
|
// create the telegram
|
||||||
auto telegram = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length);
|
auto telegram = std::make_shared<Telegram>(operation, src, dest, type_id, offset, message_data, message_length);
|
||||||
|
|
||||||
@@ -236,8 +233,8 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add empty telegram to rx-queue
|
// add empty telegram to rx-queue
|
||||||
void RxService::add_empty(const uint8_t src, const uint8_t dest, const uint16_t type_id) {
|
void RxService::add_empty(const uint8_t src, const uint8_t dest, const uint16_t type_id, uint8_t offset) {
|
||||||
auto telegram = std::make_shared<Telegram>(Telegram::Operation::RX, src, dest, type_id, 0, nullptr, 0);
|
auto telegram = std::make_shared<Telegram>(Telegram::Operation::RX, src, dest, type_id, offset, nullptr, 0);
|
||||||
// only if queue is not full
|
// only if queue is not full
|
||||||
if (rx_telegrams_.size() < MAX_RX_TELEGRAMS) {
|
if (rx_telegrams_.size() < MAX_RX_TELEGRAMS) {
|
||||||
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
|
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
|
||||||
@@ -312,9 +309,6 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
|
|||||||
// fix the READ or WRITE depending on the operation
|
// fix the READ or WRITE depending on the operation
|
||||||
uint8_t dest = telegram->dest;
|
uint8_t dest = telegram->dest;
|
||||||
|
|
||||||
// check if we have to manipulate the id for thermostats > 0x18
|
|
||||||
dest = EMSESP::check_master_device(dest, telegram->type_id, false);
|
|
||||||
|
|
||||||
if (telegram->operation == Telegram::Operation::TX_READ) {
|
if (telegram->operation == Telegram::Operation::TX_READ) {
|
||||||
dest |= 0x80; // read has 8th bit set for the destination
|
dest |= 0x80; // read has 8th bit set for the destination
|
||||||
}
|
}
|
||||||
@@ -591,20 +585,23 @@ void TxService::send_raw(const char * telegram_data) {
|
|||||||
void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const uint8_t length) {
|
void TxService::retry_tx(const uint8_t operation, const uint8_t * data, const uint8_t length) {
|
||||||
// have we reached the limit? if so, reset count and give up
|
// have we reached the limit? if so, reset count and give up
|
||||||
if (++retry_count_ > MAXIMUM_TX_RETRIES) {
|
if (++retry_count_ > MAXIMUM_TX_RETRIES) {
|
||||||
reset_retry_count(); // give up
|
reset_retry_count(); // give up
|
||||||
|
EMSESP::wait_validate(0); // do not wait for validation
|
||||||
if (operation == Telegram::Operation::TX_READ) {
|
if (operation == Telegram::Operation::TX_READ) {
|
||||||
|
if (telegram_last_->offset > 0) { // ignore errors for higher offsets
|
||||||
|
LOG_DEBUG(F("Last Tx Read operation failed after %d retries. Ignoring request: %s"), MAXIMUM_TX_RETRIES, telegram_last_->to_string().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
increment_telegram_read_fail_count(); // another Tx fail
|
increment_telegram_read_fail_count(); // another Tx fail
|
||||||
} else {
|
} else {
|
||||||
increment_telegram_write_fail_count(); // another Tx fail
|
increment_telegram_write_fail_count(); // another Tx fail
|
||||||
}
|
}
|
||||||
EMSESP::wait_validate(0); // do not wait for validation
|
|
||||||
|
|
||||||
LOG_ERROR(F("Last Tx %s operation failed after %d retries. Ignoring request: %s"),
|
LOG_ERROR(F("Last Tx %s operation failed after %d retries. Ignoring request: %s"),
|
||||||
(operation == Telegram::Operation::TX_WRITE) ? F("Write") : F("Read"),
|
(operation == Telegram::Operation::TX_WRITE) ? F("Write") : F("Read"),
|
||||||
MAXIMUM_TX_RETRIES,
|
MAXIMUM_TX_RETRIES,
|
||||||
telegram_last_->to_string().c_str());
|
telegram_last_->to_string().c_str());
|
||||||
if (operation == Telegram::Operation::TX_READ) {
|
if (operation == Telegram::Operation::TX_READ) {
|
||||||
EMSESP::rxservice_.add_empty(telegram_last_->dest, telegram_last_->src, telegram_last_->type_id);
|
EMSESP::rxservice_.add_empty(telegram_last_->dest, telegram_last_->src, telegram_last_->type_id, telegram_last_->offset);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class RxService : public EMSbus {
|
|||||||
|
|
||||||
void loop();
|
void loop();
|
||||||
void add(uint8_t * data, uint8_t length);
|
void add(uint8_t * data, uint8_t length);
|
||||||
void add_empty(const uint8_t src, const uint8_t dst, const uint16_t type_id);
|
void add_empty(const uint8_t src, const uint8_t dst, const uint16_t type_id, uint8_t offset);
|
||||||
|
|
||||||
uint32_t telegram_count() const {
|
uint32_t telegram_count() const {
|
||||||
return telegram_count_;
|
return telegram_count_;
|
||||||
|
|||||||
@@ -692,6 +692,27 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59");
|
EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(EMSESP_STANDALONE)
|
||||||
|
// https://github.com/emsesp/EMS-ESP32/issues/541
|
||||||
|
if (command == "api_wwmode") {
|
||||||
|
shell.printfln(F("Testing API wwmode"));
|
||||||
|
Mqtt::ha_enabled(false);
|
||||||
|
Mqtt::nested_format(1);
|
||||||
|
run_test("310");
|
||||||
|
|
||||||
|
AsyncWebServerRequest request;
|
||||||
|
request.method(HTTP_POST);
|
||||||
|
DynamicJsonDocument doc(2000);
|
||||||
|
JsonVariant json;
|
||||||
|
|
||||||
|
char data[] = "{\"value\":\"off\"}";
|
||||||
|
deserializeJson(doc, data);
|
||||||
|
json = doc.as<JsonVariant>();
|
||||||
|
request.url("/api/thermostat/wwmode");
|
||||||
|
EMSESP::webAPIService.webAPIService_post(&request, json);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (command == "api") {
|
if (command == "api") {
|
||||||
shell.printfln(F("Testing API with MQTT and REST, standalone"));
|
shell.printfln(F("Testing API with MQTT and REST, standalone"));
|
||||||
|
|
||||||
@@ -1638,7 +1659,7 @@ void Test::debug(uuid::console::Shell & shell, const std::string & cmd) {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (command == "ls") {
|
if (command == "ls") {
|
||||||
listDir(LITTLEFS, "/", 3);
|
listDir(LittleFS, "/", 3);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace emsesp {
|
|||||||
// #define EMSESP_DEBUG_DEFAULT "web"
|
// #define EMSESP_DEBUG_DEFAULT "web"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "general"
|
// #define EMSESP_DEBUG_DEFAULT "general"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "boiler"
|
#define EMSESP_DEBUG_DEFAULT "boiler"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt2"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
// #define EMSESP_DEBUG_DEFAULT "mqtt_nested"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "ha"
|
// #define EMSESP_DEBUG_DEFAULT "ha"
|
||||||
@@ -48,8 +48,9 @@ namespace emsesp {
|
|||||||
// #define EMSESP_DEBUG_DEFAULT "2thermostats"
|
// #define EMSESP_DEBUG_DEFAULT "2thermostats"
|
||||||
// #define EMSESP_DEBUG_DEFAULT "dallas"
|
// #define EMSESP_DEBUG_DEFAULT "dallas"
|
||||||
// #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"
|
||||||
|
// #define EMSESP_DEBUG_DEFAULT "api_wwmode"
|
||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -20,127 +20,87 @@
|
|||||||
* ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380
|
* ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(ESP32)
|
#ifndef EMSESP_STANDALONE
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
|
#include "driver/uart.h"
|
||||||
|
#include "soc/uart_reg.h"
|
||||||
#include "uart/emsuart_esp32.h"
|
#include "uart/emsuart_esp32.h"
|
||||||
|
|
||||||
#include "emsesp.h"
|
#include "emsesp.h"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
RingbufHandle_t buf_handle_ = NULL;
|
static QueueHandle_t uart_queue;
|
||||||
portMUX_TYPE mux_ = portMUX_INITIALIZER_UNLOCKED;
|
uint8_t tx_mode_ = 0xFF;
|
||||||
bool drop_next_rx_ = true;
|
|
||||||
uint8_t tx_mode_ = 0xFF;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Task to handle the incoming data
|
* receive task, wait for break and call incoming_telegram
|
||||||
*/
|
*/
|
||||||
void EMSuart::emsuart_recvTask(void * para) {
|
void EMSuart::uart_event_task(void * pvParameters) {
|
||||||
while (1) {
|
uart_event_t event;
|
||||||
size_t item_size;
|
uint8_t telegram[EMS_MAXBUFFERSIZE];
|
||||||
uint8_t * telegram = (uint8_t *)xRingbufferReceive(buf_handle_, &item_size, portMAX_DELAY);
|
uint8_t length = 0;
|
||||||
uint8_t telegramSize = item_size;
|
|
||||||
if (telegram) {
|
|
||||||
EMSESP::incoming_telegram(telegram, telegramSize);
|
|
||||||
vRingbufferReturnItem(buf_handle_, (void *)telegram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
while (1) {
|
||||||
* UART interrupt, on break read the fifo and put the whole telegram to ringbuffer
|
//Waiting for UART event.
|
||||||
*/
|
if (xQueueReceive(uart_queue, (void *)&event, portMAX_DELAY)) {
|
||||||
void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
|
if (event.type == UART_DATA) {
|
||||||
portENTER_CRITICAL(&mux_);
|
length += event.size;
|
||||||
if (EMS_UART.int_st.brk_det) {
|
} else if (event.type == UART_BREAK) {
|
||||||
EMS_UART.int_clr.brk_det = 1; // clear flag
|
if (length == 2 || (length >= 6 && length <= EMS_MAXBUFFERSIZE)) {
|
||||||
uint8_t rxbuf[EMS_MAXBUFFERSIZE];
|
uart_read_bytes(EMSUART_NUM, telegram, length, portMAX_DELAY);
|
||||||
uint8_t length = 0;
|
// if (telegram[0] && !telegram[length - 1]) {
|
||||||
while (EMS_UART.status.rxfifo_cnt) {
|
EMSESP::incoming_telegram(telegram, (uint8_t)(length - 1));
|
||||||
uint8_t rx = EMS_UART.fifo.rw_byte; // read all bytes from fifo
|
// }
|
||||||
if (length < EMS_MAXBUFFERSIZE) {
|
} else {
|
||||||
if (length || rx) { // skip leading zero
|
// flush buffer up to break
|
||||||
rxbuf[length++] = rx;
|
uint8_t buf[length];
|
||||||
|
uart_read_bytes(EMSUART_NUM, buf, length, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
} else {
|
length = 0;
|
||||||
drop_next_rx_ = true; // we have a overflow
|
} else if (event.type == UART_BUFFER_FULL) {
|
||||||
|
uart_flush_input(EMSUART_NUM);
|
||||||
|
length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (length > 0 && length < EMS_MAXBUFFERSIZE) {
|
|
||||||
if (rxbuf[length - 1]) { // check if last byte is break
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((!drop_next_rx_) && ((length == 2) || (length > 4))) {
|
|
||||||
int baseType = 0;
|
|
||||||
xRingbufferSendFromISR(buf_handle_, rxbuf, length - 1, &baseType);
|
|
||||||
}
|
|
||||||
drop_next_rx_ = false;
|
|
||||||
}
|
}
|
||||||
portEXIT_CRITICAL(&mux_);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* init UART driver
|
* init UART driver
|
||||||
*/
|
*/
|
||||||
void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) {
|
void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) {
|
||||||
if (tx_mode_ != 0xFF) { // uart already initialized
|
if (tx_mode_ == 0xFF) {
|
||||||
tx_mode_ = tx_mode;
|
uart_config_t uart_config = {
|
||||||
restart();
|
.baud_rate = EMSUART_BAUD,
|
||||||
return;
|
.data_bits = UART_DATA_8_BITS,
|
||||||
|
.parity = UART_PARITY_DISABLE,
|
||||||
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||||
|
.source_clk = UART_SCLK_APB,
|
||||||
|
};
|
||||||
|
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
|
||||||
|
uart_param_config(EMSUART_NUM, &uart_config);
|
||||||
|
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||||
|
uart_set_rx_full_threshold(EMSUART_NUM, 1);
|
||||||
|
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
|
||||||
|
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||||
}
|
}
|
||||||
tx_mode_ = tx_mode;
|
tx_mode_ = tx_mode;
|
||||||
portENTER_CRITICAL(&mux_);
|
uart_enable_intr_mask(EMSUART_NUM, UART_BRK_DET_INT_ENA | UART_RXFIFO_FULL_INT_ENA);
|
||||||
uart_config_t uart_config = {
|
|
||||||
.baud_rate = EMSUART_BAUD,
|
|
||||||
.data_bits = UART_DATA_8_BITS,
|
|
||||||
.parity = UART_PARITY_DISABLE,
|
|
||||||
.stop_bits = UART_STOP_BITS_1,
|
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
|
||||||
};
|
|
||||||
|
|
||||||
uart_param_config(EMSUART_UART, &uart_config);
|
|
||||||
uart_set_pin(EMSUART_UART, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
|
||||||
EMS_UART.int_ena.val = 0; // disable all intr.
|
|
||||||
EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags
|
|
||||||
EMS_UART.idle_conf.tx_brk_num = 10; // breaklength 10 bit
|
|
||||||
drop_next_rx_ = true;
|
|
||||||
// EMS_UART.idle_conf.rx_idle_thrhd = 256;
|
|
||||||
// EMS_UART.auto_baud.glitch_filt = 192;
|
|
||||||
#if (EMSUART_UART != UART_NUM_2)
|
|
||||||
EMS_UART.conf0.rxfifo_rst = 1; // flush fifos, remove for UART2
|
|
||||||
EMS_UART.conf0.txfifo_rst = 1;
|
|
||||||
#endif
|
|
||||||
buf_handle_ = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT);
|
|
||||||
uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL);
|
|
||||||
xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, configMAX_PRIORITIES - 3, NULL);
|
|
||||||
portEXIT_CRITICAL(&mux_);
|
|
||||||
restart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stop, disable interrupt
|
* Stop, disable interrupt
|
||||||
*/
|
*/
|
||||||
void EMSuart::stop() {
|
void EMSuart::stop() {
|
||||||
portENTER_CRITICAL(&mux_);
|
if (tx_mode_ != 0xFF) { // only call after driver initialisation
|
||||||
EMS_UART.int_ena.val = 0; // disable all intr.
|
uart_disable_intr_mask(EMSUART_NUM, UART_BRK_DET_INT_ENA | UART_RXFIFO_FULL_INT_ENA);
|
||||||
portEXIT_CRITICAL(&mux_);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Restart uart and make mode dependent configs.
|
|
||||||
*/
|
|
||||||
void EMSuart::restart() {
|
|
||||||
portENTER_CRITICAL(&mux_);
|
|
||||||
if (EMS_UART.int_raw.brk_det) { // we received a break in the meantime
|
|
||||||
EMS_UART.int_clr.brk_det = 1; // clear flag
|
|
||||||
drop_next_rx_ = true; // and drop first frame
|
|
||||||
}
|
}
|
||||||
EMS_UART.int_ena.brk_det = 1; // activate only break
|
};
|
||||||
EMS_UART.conf0.txd_brk = (tx_mode_ == EMS_TXMODE_HW) ? 1 : 0;
|
|
||||||
portEXIT_CRITICAL(&mux_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sends a 1-byte poll, ending with a <BRK>
|
* Sends a 1-byte poll, ending with a <BRK>
|
||||||
@@ -164,49 +124,46 @@ uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tx_mode_ == EMS_TXMODE_HW) { // hardware controlled mode
|
if (tx_mode_ == EMS_TXMODE_HW) { // hardware controlled mode
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
uart_write_bytes_with_break(EMSUART_NUM, buf, len, 10);
|
||||||
EMS_UART.fifo.rw_byte = buf[i];
|
|
||||||
}
|
|
||||||
return EMS_TX_STATUS_OK;
|
return EMS_TX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ with long delay
|
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ with long delay
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
EMS_UART.fifo.rw_byte = buf[i];
|
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
||||||
}
|
}
|
||||||
EMS_UART.conf0.txd_inv = 1; // send <brk>
|
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
|
||||||
delayMicroseconds(EMSUART_TX_BRK_PLUS);
|
delayMicroseconds(EMSUART_TX_BRK_PLUS);
|
||||||
EMS_UART.conf0.txd_inv = 0;
|
uart_set_line_inverse(EMSUART_NUM, 0);
|
||||||
return EMS_TX_STATUS_OK;
|
return EMS_TX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx_mode_ == EMS_TXMODE_HT3) { // HT3 with 7 bittimes delay
|
if (tx_mode_ == EMS_TXMODE_HT3) { // HT3 with 7 bittimes delay
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
EMS_UART.fifo.rw_byte = buf[i];
|
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
||||||
}
|
}
|
||||||
EMS_UART.conf0.txd_inv = 1; // send <brk>
|
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
|
||||||
delayMicroseconds(EMSUART_TX_BRK_HT3);
|
delayMicroseconds(EMSUART_TX_BRK_HT3);
|
||||||
EMS_UART.conf0.txd_inv = 0;
|
uart_set_line_inverse(EMSUART_NUM, 0);
|
||||||
return EMS_TX_STATUS_OK;
|
return EMS_TX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mode 1: wait for echo after each byte
|
// mode 1: wait for echo after each byte
|
||||||
// flush fifos -- not supported in ESP32 uart #2!
|
|
||||||
// EMS_UART.conf0.rxfifo_rst = 1;
|
|
||||||
// EMS_UART.conf0.txfifo_rst = 1;
|
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt;
|
size_t rx0, rx1;
|
||||||
EMS_UART.fifo.rw_byte = buf[i]; // send each Tx byte
|
uart_get_buffered_data_len(EMSUART_NUM, &rx0);
|
||||||
uint16_t timeoutcnt = EMSUART_TX_TIMEOUT;
|
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
||||||
while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) {
|
uint16_t timeoutcnt = EMSUART_TX_TIMEOUT;
|
||||||
|
do {
|
||||||
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
|
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
|
||||||
}
|
uart_get_buffered_data_len(EMSUART_NUM, &rx1);
|
||||||
|
} while ((rx1 == rx0) && (--timeoutcnt));
|
||||||
}
|
}
|
||||||
EMS_UART.conf0.txd_inv = 1;
|
uart_set_line_inverse(EMSUART_NUM, UART_SIGNAL_TXD_INV);
|
||||||
delayMicroseconds(EMSUART_TX_BRK_EMS);
|
delayMicroseconds(EMSUART_TX_BRK_EMS);
|
||||||
EMS_UART.conf0.txd_inv = 0;
|
uart_set_line_inverse(EMSUART_NUM, 0);
|
||||||
return EMS_TX_STATUS_OK;
|
return EMS_TX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,25 +20,15 @@
|
|||||||
/*
|
/*
|
||||||
* ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380
|
* ESP32 UART port by @ArwedL and improved by @MichaelDvP. See https://github.com/emsesp/EMS-ESP/issues/380
|
||||||
*/
|
*/
|
||||||
#if defined(ESP32)
|
|
||||||
|
|
||||||
#ifndef EMSESP_EMSUART_H
|
#ifndef EMSESP_EMSUART_H
|
||||||
#define EMSESP_EMSUART_H
|
#define EMSESP_EMSUART_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/ringbuf.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
#include <driver/uart.h>
|
|
||||||
#include <driver/timer.h>
|
|
||||||
|
|
||||||
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
|
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
|
||||||
|
|
||||||
#define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2
|
#define EMSUART_NUM UART_NUM_2 // on the ESP32 we're using UART2
|
||||||
#define EMS_UART UART2 // for intr setting
|
#define EMSUART UART2 // for intr setting
|
||||||
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
|
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
|
||||||
|
|
||||||
#define EMS_TXMODE_DEFAULT 1
|
#define EMS_TXMODE_DEFAULT 1
|
||||||
#define EMS_TXMODE_EMSPLUS 2
|
#define EMS_TXMODE_EMSPLUS 2
|
||||||
@@ -78,12 +68,9 @@ class EMSuart {
|
|||||||
static uint16_t transmit(const uint8_t * buf, const uint8_t len);
|
static uint16_t transmit(const uint8_t * buf, const uint8_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void emsuart_recvTask(void * para);
|
static void uart_event_task(void * pvParameters);
|
||||||
static void IRAM_ATTR emsuart_rx_intr_handler(void * para);
|
|
||||||
static void restart();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.4.1"
|
#define EMSESP_APP_VERSION "3.4.2"
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// SUrlParser from https://github.com/Mad-ness/simple-url-parser
|
|
||||||
|
|
||||||
#include "emsesp.h"
|
#include "emsesp.h"
|
||||||
|
|
||||||
using namespace std::placeholders; // for `_1` etc
|
using namespace std::placeholders; // for `_1` etc
|
||||||
@@ -158,7 +156,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebAPIService::getSettings(AsyncWebServerRequest * request) {
|
void WebAPIService::getSettings(AsyncWebServerRequest * request) {
|
||||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN);
|
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
root["type"] = "settings";
|
root["type"] = "settings";
|
||||||
@@ -179,7 +177,7 @@ void WebAPIService::getSettings(AsyncWebServerRequest * request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebAPIService::getCustomizations(AsyncWebServerRequest * request) {
|
void WebAPIService::getCustomizations(AsyncWebServerRequest * request) {
|
||||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN);
|
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
root["type"] = "customizations";
|
root["type"] = "customizations";
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
|||||||
// deletes the customization file
|
// deletes the customization file
|
||||||
void WebCustomizationService::reset_customization(AsyncWebServerRequest * request) {
|
void WebCustomizationService::reset_customization(AsyncWebServerRequest * request) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (LITTLEFS.remove(EMSESP_CUSTOMIZATION_FILE)) {
|
if (LittleFS.remove(EMSESP_CUSTOMIZATION_FILE)) {
|
||||||
AsyncWebServerResponse * response = request->beginResponse(200); // OK
|
AsyncWebServerResponse * response = request->beginResponse(200); // OK
|
||||||
request->send(response);
|
request->send(response);
|
||||||
EMSESP::system_.restart_requested(true);
|
EMSESP::system_.restart_requested(true);
|
||||||
@@ -165,22 +165,27 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
|||||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN);
|
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
|
// list is already sorted by device type
|
||||||
|
// controller is ignored since it doesn't have any associated entities
|
||||||
JsonArray devices = root.createNestedArray("devices");
|
JsonArray devices = root.createNestedArray("devices");
|
||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice->has_entities()) {
|
if (emsdevice->has_entities()) {
|
||||||
JsonObject obj = devices.createNestedObject();
|
JsonObject obj = devices.createNestedObject();
|
||||||
obj["i"] = emsdevice->unique_id(); // a unique id
|
obj["i"] = emsdevice->unique_id(); // its unique id
|
||||||
|
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")"; // shortname
|
||||||
|
|
||||||
|
// device type name. We may have one than one (e.g. multiple thermostats) so postfix name with index
|
||||||
|
// code block not needed - see https://github.com/emsesp/EMS-ESP32/pull/586#issuecomment-1193779668
|
||||||
/*
|
/*
|
||||||
uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
|
uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
|
||||||
if (device_index) {
|
if (device_index) {
|
||||||
char s[10];
|
char s[10];
|
||||||
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; // shortname - we prefix the count to make it unique
|
obj["t"] = Helpers::toLower(emsdevice->device_type_name()) + Helpers::smallitoa(s, device_index);
|
||||||
} else {
|
} else {
|
||||||
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
|
obj["t"] = Helpers::toLower(emsdevice->device_type_name());
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
|
obj["t"] = Helpers::toLower(emsdevice->device_type_name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user