mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 00:39:50 +03:00
determine list of valid gpios in backend code
This commit is contained in:
@@ -54,7 +54,7 @@ const MS_PER_SECOND = 1000;
|
|||||||
const MS_PER_MINUTE = 60 * MS_PER_SECOND;
|
const MS_PER_MINUTE = 60 * MS_PER_SECOND;
|
||||||
const MS_PER_HOUR = 60 * MS_PER_MINUTE;
|
const MS_PER_HOUR = 60 * MS_PER_MINUTE;
|
||||||
const MS_PER_DAY = 24 * MS_PER_HOUR;
|
const MS_PER_DAY = 24 * MS_PER_HOUR;
|
||||||
const DEFAULT_GPIO = 21; // Safe GPIO for all platforms
|
const DEFAULT_GPIO = -1; // not set
|
||||||
const MIN_TEMP_ID = -100;
|
const MIN_TEMP_ID = -100;
|
||||||
const MAX_TEMP_ID = 100;
|
const MAX_TEMP_ID = 100;
|
||||||
const GPIO_25 = 25;
|
const GPIO_25 = 25;
|
||||||
@@ -134,6 +134,7 @@ const Sensors = () => {
|
|||||||
ts: [],
|
ts: [],
|
||||||
as: [],
|
as: [],
|
||||||
analog_enabled: false,
|
analog_enabled: false,
|
||||||
|
valid_gpio_list: [],
|
||||||
platform: 'ESP32'
|
platform: 'ESP32'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -573,10 +574,10 @@ const Sensors = () => {
|
|||||||
onSave={onAnalogDialogSave}
|
onSave={onAnalogDialogSave}
|
||||||
creating={creating}
|
creating={creating}
|
||||||
selectedItem={selectedAnalogSensor}
|
selectedItem={selectedAnalogSensor}
|
||||||
|
analogGPIOList={sensorData.valid_gpio_list}
|
||||||
validator={analogSensorItemValidation(
|
validator={analogSensorItemValidation(
|
||||||
sensorData.as,
|
sensorData.as,
|
||||||
selectedAnalogSensor,
|
selectedAnalogSensor,
|
||||||
creating,
|
|
||||||
sensorData.platform
|
sensorData.platform
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ interface DashboardSensorsAnalogDialogProps {
|
|||||||
onSave: (as: AnalogSensor) => void;
|
onSave: (as: AnalogSensor) => void;
|
||||||
creating: boolean;
|
creating: boolean;
|
||||||
selectedItem: AnalogSensor;
|
selectedItem: AnalogSensor;
|
||||||
|
analogGPIOList: number[];
|
||||||
validator: Schema;
|
validator: Schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ const SensorsAnalogDialog = ({
|
|||||||
onSave,
|
onSave,
|
||||||
creating,
|
creating,
|
||||||
selectedItem,
|
selectedItem,
|
||||||
|
analogGPIOList,
|
||||||
validator
|
validator
|
||||||
}: DashboardSensorsAnalogDialogProps) => {
|
}: DashboardSensorsAnalogDialogProps) => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
@@ -156,28 +158,23 @@ const SensorsAnalogDialog = ({
|
|||||||
<DialogTitle>{dialogTitle}</DialogTitle>
|
<DialogTitle>{dialogTitle}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="g"
|
name="g"
|
||||||
label="GPIO"
|
label="GPIO"
|
||||||
sx={{ width: '11ch' }}
|
value={editItem.g}
|
||||||
value={numberValue(editItem.g)}
|
sx={{ width: '8ch' }}
|
||||||
type="number"
|
select
|
||||||
variant="outlined"
|
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
/>
|
disabled={editItem.s}
|
||||||
</Grid>
|
>
|
||||||
{creating && (
|
{analogGPIOList?.map((gpio: number) => (
|
||||||
<Grid>
|
<MenuItem key={gpio} value={gpio}>
|
||||||
<Box color="warning.main" mt={2}>
|
{gpio}
|
||||||
<Typography variant="body2">{LL.WARN_GPIO()}</Typography>
|
</MenuItem>
|
||||||
</Box>
|
))}
|
||||||
</Grid>
|
</ValidatedTextField>
|
||||||
)}
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<ValidatedTextField
|
<ValidatedTextField
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="n"
|
name="n"
|
||||||
label={LL.NAME(0)}
|
label={LL.NAME(0)}
|
||||||
value={editItem.n}
|
value={editItem.n}
|
||||||
@@ -194,6 +191,7 @@ const SensorsAnalogDialog = ({
|
|||||||
fullWidth
|
fullWidth
|
||||||
select
|
select
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
{analogTypeMenuItems}
|
{analogTypeMenuItems}
|
||||||
</TextField>
|
</TextField>
|
||||||
@@ -207,6 +205,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '15ch' }}
|
sx={{ width: '15ch' }}
|
||||||
select
|
select
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
{uomMenuItems}
|
{uomMenuItems}
|
||||||
</TextField>
|
</TextField>
|
||||||
@@ -222,6 +221,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
@@ -243,6 +243,7 @@ const SensorsAnalogDialog = ({
|
|||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
@@ -264,6 +265,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
htmlInput: { step: '0.001' }
|
htmlInput: { step: '0.001' }
|
||||||
}}
|
}}
|
||||||
@@ -280,6 +282,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
@@ -293,6 +296,7 @@ const SensorsAnalogDialog = ({
|
|||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
htmlInput: { step: '0.001' }
|
htmlInput: { step: '0.001' }
|
||||||
}}
|
}}
|
||||||
@@ -309,6 +313,7 @@ const SensorsAnalogDialog = ({
|
|||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
htmlInput: { min: '0', max: '255', step: '1' }
|
htmlInput: { min: '0', max: '255', step: '1' }
|
||||||
}}
|
}}
|
||||||
@@ -325,6 +330,7 @@ const SensorsAnalogDialog = ({
|
|||||||
select
|
select
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
<MenuItem value={0}>{LL.OFF()}</MenuItem>
|
<MenuItem value={0}>{LL.OFF()}</MenuItem>
|
||||||
<MenuItem value={1}>{LL.ON()}</MenuItem>
|
<MenuItem value={1}>{LL.ON()}</MenuItem>
|
||||||
@@ -338,6 +344,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '15ch' }}
|
sx={{ width: '15ch' }}
|
||||||
select
|
select
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
<MenuItem value={1}>{LL.ACTIVEHIGH()}</MenuItem>
|
<MenuItem value={1}>{LL.ACTIVEHIGH()}</MenuItem>
|
||||||
<MenuItem value={-1}>{LL.ACTIVELOW()}</MenuItem>
|
<MenuItem value={-1}>{LL.ACTIVELOW()}</MenuItem>
|
||||||
@@ -351,6 +358,7 @@ const SensorsAnalogDialog = ({
|
|||||||
value={editItem.u}
|
value={editItem.u}
|
||||||
select
|
select
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
<MenuItem value={0}>{LL.UNCHANGED()}</MenuItem>
|
<MenuItem value={0}>{LL.UNCHANGED()}</MenuItem>
|
||||||
<MenuItem value={1}>
|
<MenuItem value={1}>
|
||||||
@@ -374,6 +382,7 @@ const SensorsAnalogDialog = ({
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
@@ -393,6 +402,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
@@ -415,6 +425,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '11ch' }}
|
sx={{ width: '11ch' }}
|
||||||
select
|
select
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
>
|
>
|
||||||
<MenuItem value={0}>{LL.ACTIVEHIGH()}</MenuItem>
|
<MenuItem value={0}>{LL.ACTIVEHIGH()}</MenuItem>
|
||||||
<MenuItem value={1}>{LL.ACTIVELOW()}</MenuItem>
|
<MenuItem value={1}>{LL.ACTIVELOW()}</MenuItem>
|
||||||
@@ -429,6 +440,7 @@ const SensorsAnalogDialog = ({
|
|||||||
sx={{ width: '15ch' }}
|
sx={{ width: '15ch' }}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onChange={updateFormValue}
|
onChange={updateFormValue}
|
||||||
|
disabled={editItem.s}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
input: {
|
input: {
|
||||||
startAdornment: (
|
startAdornment: (
|
||||||
@@ -442,6 +454,24 @@ const SensorsAnalogDialog = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{fieldErrors && Object.keys(fieldErrors).length > 0 && (
|
||||||
|
<Box mt={1}>
|
||||||
|
{Object.values(fieldErrors).map((errArr, idx) =>
|
||||||
|
Array.isArray(errArr)
|
||||||
|
? errArr.map((err, j) => (
|
||||||
|
<Typography
|
||||||
|
key={`${idx}-${j}`}
|
||||||
|
color="error"
|
||||||
|
variant="caption"
|
||||||
|
display="block"
|
||||||
|
>
|
||||||
|
{err.message}
|
||||||
|
</Typography>
|
||||||
|
))
|
||||||
|
: null
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
{editItem.s && (
|
{editItem.s && (
|
||||||
<Grid>
|
<Grid>
|
||||||
<Typography mt={1} color="warning.main" variant="body2">
|
<Typography mt={1} color="warning.main" variant="body2">
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ export interface SensorData {
|
|||||||
ts: TemperatureSensor[];
|
ts: TemperatureSensor[];
|
||||||
as: AnalogSensor[];
|
as: AnalogSensor[];
|
||||||
analog_enabled: boolean;
|
analog_enabled: boolean;
|
||||||
|
valid_gpio_list: number[];
|
||||||
platform: string;
|
platform: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,121 +45,15 @@ const VALIDATION_LIMITS = {
|
|||||||
HEX_BASE: 16
|
HEX_BASE: 16
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Helper to create GPIO validator from invalid ranges
|
|
||||||
const createGPIOValidator = (
|
|
||||||
invalidRanges: Array<number | [number, number]>,
|
|
||||||
maxValue: number
|
|
||||||
) => ({
|
|
||||||
validator(
|
|
||||||
_rule: InternalRuleItem,
|
|
||||||
value: number,
|
|
||||||
callback: (error?: string) => void
|
|
||||||
) {
|
|
||||||
if (!value) {
|
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < 0 || value > maxValue) {
|
|
||||||
callback(ERROR_MESSAGES.GPIO_INVALID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const range of invalidRanges) {
|
|
||||||
if (typeof range === 'number') {
|
|
||||||
if (value === range) {
|
|
||||||
callback(ERROR_MESSAGES.GPIO_INVALID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const [start, end] = range;
|
|
||||||
if (value >= start && value <= end) {
|
|
||||||
callback(ERROR_MESSAGES.GPIO_INVALID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const GPIO_VALIDATOR = createGPIOValidator(
|
|
||||||
[[6, 11], 1, 20, 24, [28, 31]],
|
|
||||||
40
|
|
||||||
);
|
|
||||||
|
|
||||||
export const GPIO_VALIDATORC3 = createGPIOValidator([[11, 19]], 21);
|
|
||||||
|
|
||||||
export const GPIO_VALIDATORS2 = createGPIOValidator(
|
|
||||||
[
|
|
||||||
[19, 20],
|
|
||||||
[22, 32]
|
|
||||||
],
|
|
||||||
40
|
|
||||||
);
|
|
||||||
|
|
||||||
export const GPIO_VALIDATORS3 = createGPIOValidator(
|
|
||||||
[
|
|
||||||
[19, 20],
|
|
||||||
[22, 37],
|
|
||||||
[39, 42]
|
|
||||||
],
|
|
||||||
48
|
|
||||||
);
|
|
||||||
|
|
||||||
const GPIO_FIELD_NAMES = [
|
|
||||||
'led_gpio',
|
|
||||||
'dallas_gpio',
|
|
||||||
'pbutton_gpio',
|
|
||||||
'tx_gpio',
|
|
||||||
'rx_gpio'
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
type ValidationRules = Array<{
|
type ValidationRules = Array<{
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
message?: string;
|
message?: string;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const createGPIOValidations = (
|
|
||||||
validator: typeof GPIO_VALIDATOR
|
|
||||||
): Record<string, ValidationRules> =>
|
|
||||||
GPIO_FIELD_NAMES.reduce(
|
|
||||||
(acc, field) => {
|
|
||||||
const fieldName = field.replace('_gpio', '').toUpperCase();
|
|
||||||
acc[field] = [
|
|
||||||
{ required: true, message: `${fieldName} GPIO is required` },
|
|
||||||
validator
|
|
||||||
];
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{} as Record<string, ValidationRules>
|
|
||||||
);
|
|
||||||
|
|
||||||
const PLATFORM_VALIDATORS = {
|
|
||||||
ESP32: GPIO_VALIDATOR,
|
|
||||||
ESP32C3: GPIO_VALIDATORC3,
|
|
||||||
ESP32S2: GPIO_VALIDATORS2,
|
|
||||||
ESP32S3: GPIO_VALIDATORS3
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export const createSettingsValidator = (settings: Settings) => {
|
export const createSettingsValidator = (settings: Settings) => {
|
||||||
const schema: Record<string, ValidationRules> = {};
|
const schema: Record<string, ValidationRules> = {};
|
||||||
|
|
||||||
// Add GPIO validations for CUSTOM board profiles
|
|
||||||
if (
|
|
||||||
settings.board_profile === 'CUSTOM' &&
|
|
||||||
settings.platform in PLATFORM_VALIDATORS
|
|
||||||
) {
|
|
||||||
Object.assign(
|
|
||||||
schema,
|
|
||||||
createGPIOValidations(
|
|
||||||
PLATFORM_VALIDATORS[settings.platform as keyof typeof PLATFORM_VALIDATORS]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syslog validations
|
// Syslog validations
|
||||||
if (settings.syslog_enabled) {
|
if (settings.syslog_enabled) {
|
||||||
schema.syslog_host = [
|
schema.syslog_host = [
|
||||||
@@ -401,52 +295,29 @@ export const temperatureSensorItemValidation = (
|
|||||||
n: [NAME_PATTERN, uniqueTemperatureNameValidator(sensors, sensor.o_n)]
|
n: [NAME_PATTERN, uniqueTemperatureNameValidator(sensors, sensor.o_n)]
|
||||||
});
|
});
|
||||||
|
|
||||||
export const isGPIOUniqueValidator = (sensors: AnalogSensor[]) => ({
|
|
||||||
validator(
|
|
||||||
_rule: InternalRuleItem,
|
|
||||||
gpio: number,
|
|
||||||
callback: (error?: string) => void
|
|
||||||
) {
|
|
||||||
if (sensors.some((as) => as.g === gpio)) {
|
|
||||||
callback(ERROR_MESSAGES.GPIO_DUPLICATE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const uniqueAnalogNameValidator = (
|
export const uniqueAnalogNameValidator = (
|
||||||
sensors: AnalogSensor[],
|
sensors: AnalogSensor[],
|
||||||
o_name?: string
|
o_name?: string
|
||||||
) => createUniqueFieldNameValidator(sensors, (s) => s.n, o_name);
|
) => createUniqueFieldNameValidator(sensors, (s) => s.n, o_name);
|
||||||
|
|
||||||
const getPlatformGPIOValidator = (platform: string) => {
|
|
||||||
switch (platform) {
|
|
||||||
case 'ESP32S3':
|
|
||||||
return GPIO_VALIDATORS3;
|
|
||||||
case 'ESP32S2':
|
|
||||||
return GPIO_VALIDATORS2;
|
|
||||||
case 'ESP32C3':
|
|
||||||
return GPIO_VALIDATORC3;
|
|
||||||
default:
|
|
||||||
return GPIO_VALIDATOR;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const analogSensorItemValidation = (
|
export const analogSensorItemValidation = (
|
||||||
sensors: AnalogSensor[],
|
sensors: AnalogSensor[],
|
||||||
sensor: AnalogSensor,
|
sensor: AnalogSensor
|
||||||
creating: boolean,
|
|
||||||
platform: string
|
|
||||||
) => {
|
) => {
|
||||||
const gpioValidator = getPlatformGPIOValidator(platform);
|
|
||||||
|
|
||||||
return new Schema({
|
return new Schema({
|
||||||
n: [NAME_PATTERN, uniqueAnalogNameValidator(sensors, sensor.o_n)],
|
// name is required and must be unique
|
||||||
|
n: [
|
||||||
|
{ required: true, message: 'Name is required' },
|
||||||
|
NAME_PATTERN,
|
||||||
|
uniqueAnalogNameValidator(sensors, sensor.o_n)
|
||||||
|
],
|
||||||
g: [
|
g: [
|
||||||
{ required: true, message: 'GPIO is required' },
|
{
|
||||||
gpioValidator,
|
required: true,
|
||||||
...(creating ? [isGPIOUniqueValidator(sensors)] : [])
|
type: 'number',
|
||||||
|
min: 1,
|
||||||
|
message: 'GPIO is required'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const cz: Translation = {
|
|||||||
DUTY_CYCLE: 'Pracovní cyklus',
|
DUTY_CYCLE: 'Pracovní cyklus',
|
||||||
UNIT: 'Jednotka',
|
UNIT: 'Jednotka',
|
||||||
STARTVALUE: 'Počáteční hodnota',
|
STARTVALUE: 'Počáteční hodnota',
|
||||||
WARN_GPIO: 'Upozornění: buďte opatrní při přiřazování GPIO!',
|
|
||||||
EDIT: 'Upravit',
|
EDIT: 'Upravit',
|
||||||
SENSOR: 'Senzor',
|
SENSOR: 'Senzor',
|
||||||
TEMP_SENSOR: 'Teplotní senzor',
|
TEMP_SENSOR: 'Teplotní senzor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const de: Translation = {
|
|||||||
DUTY_CYCLE: 'Arbeitszyklus',
|
DUTY_CYCLE: 'Arbeitszyklus',
|
||||||
UNIT: 'Maßeinheit',
|
UNIT: 'Maßeinheit',
|
||||||
STARTVALUE: 'Startwert',
|
STARTVALUE: 'Startwert',
|
||||||
WARN_GPIO: 'Warnung: Vorsicht bei der korrekten Wahl des GPIO!',
|
|
||||||
EDIT: 'Editiere',
|
EDIT: 'Editiere',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
TEMP_SENSOR: 'Temperatursensor',
|
TEMP_SENSOR: 'Temperatursensor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const en: Translation = {
|
|||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Duty Cycle',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Start Value',
|
STARTVALUE: 'Start Value',
|
||||||
WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
|
|
||||||
EDIT: 'Edit',
|
EDIT: 'Edit',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
TEMP_SENSOR: 'Temperature Sensor',
|
TEMP_SENSOR: 'Temperature Sensor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const fr: Translation = {
|
|||||||
DUTY_CYCLE: 'Cycle de fonctionnement',
|
DUTY_CYCLE: 'Cycle de fonctionnement',
|
||||||
UNIT: 'Unité',
|
UNIT: 'Unité',
|
||||||
STARTVALUE: 'Valeur de départ',
|
STARTVALUE: 'Valeur de départ',
|
||||||
WARN_GPIO: 'Attention: soyez vigilant en choisissant un GPIO!',
|
|
||||||
EDIT: 'Éditer',
|
EDIT: 'Éditer',
|
||||||
SENSOR: 'Capteur',
|
SENSOR: 'Capteur',
|
||||||
TEMP_SENSOR: 'Capteur de température',
|
TEMP_SENSOR: 'Capteur de température',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const it: Translation = {
|
|||||||
DUTY_CYCLE: 'Ciclo di lavoro',
|
DUTY_CYCLE: 'Ciclo di lavoro',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Valore di partenza',
|
STARTVALUE: 'Valore di partenza',
|
||||||
WARN_GPIO: 'Avvertimento: prestare attenzione quando si assegna un GPIO!',
|
|
||||||
EDIT: 'Modifica',
|
EDIT: 'Modifica',
|
||||||
SENSOR: 'Sensore',
|
SENSOR: 'Sensore',
|
||||||
TEMP_SENSOR: 'Sensore Temperatura',
|
TEMP_SENSOR: 'Sensore Temperatura',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const nl: Translation = {
|
|||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Duty Cycle',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Startwaarde',
|
STARTVALUE: 'Startwaarde',
|
||||||
WARN_GPIO: 'Waarschuwing: let op met het koppelen van de juiste GPIO pin!',
|
|
||||||
EDIT: 'Wijzigen',
|
EDIT: 'Wijzigen',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
TEMP_SENSOR: 'Temperatuur sensor',
|
TEMP_SENSOR: 'Temperatuur sensor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const no: Translation = {
|
|||||||
DUTY_CYCLE: 'Duty Cycle',
|
DUTY_CYCLE: 'Duty Cycle',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Startverdi',
|
STARTVALUE: 'Startverdi',
|
||||||
WARN_GPIO: 'Advarsel: vær forsiktig ved aktivering av GPIO!',
|
|
||||||
EDIT: 'Endre',
|
EDIT: 'Endre',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
TEMP_SENSOR: 'Temperatursensor',
|
TEMP_SENSOR: 'Temperatursensor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const pl: BaseTranslation = {
|
|||||||
DUTY_CYCLE: 'Wypełnienie',
|
DUTY_CYCLE: 'Wypełnienie',
|
||||||
UNIT: 'J.m.',
|
UNIT: 'J.m.',
|
||||||
STARTVALUE: 'Wartość początkowa',
|
STARTVALUE: 'Wartość początkowa',
|
||||||
WARN_GPIO: 'Uwaga! Zachowaj ostrożność przypisując GPIO do urządzenia!',
|
|
||||||
EDIT: 'Edycja',
|
EDIT: 'Edycja',
|
||||||
SENSOR: '{{c|ustawienia c||ustawień c|}}zujnika',
|
SENSOR: '{{c|ustawienia c||ustawień c|}}zujnika',
|
||||||
TEMP_SENSOR: 'czujnika temperatury',
|
TEMP_SENSOR: 'czujnika temperatury',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const sk: Translation = {
|
|||||||
DUTY_CYCLE: 'Pracovný cyklus',
|
DUTY_CYCLE: 'Pracovný cyklus',
|
||||||
UNIT: 'UoM',
|
UNIT: 'UoM',
|
||||||
STARTVALUE: 'Počiatočná hodnota',
|
STARTVALUE: 'Počiatočná hodnota',
|
||||||
WARN_GPIO: 'Upozornenie: Buďte opatrní pri priraďovaní GPIO!',
|
|
||||||
EDIT: 'Editovať',
|
EDIT: 'Editovať',
|
||||||
SENSOR: 'Snímač',
|
SENSOR: 'Snímač',
|
||||||
TEMP_SENSOR: 'Snímač teploty',
|
TEMP_SENSOR: 'Snímač teploty',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const sv: Translation = {
|
|||||||
DUTY_CYCLE: 'Pulskvot',
|
DUTY_CYCLE: 'Pulskvot',
|
||||||
UNIT: 'Måttenhet',
|
UNIT: 'Måttenhet',
|
||||||
STARTVALUE: 'Startvärde',
|
STARTVALUE: 'Startvärde',
|
||||||
WARN_GPIO: 'Varning: Var försiktig vid aktivering av GPIO!',
|
|
||||||
EDIT: 'Ändra',
|
EDIT: 'Ändra',
|
||||||
SENSOR: 'Sensor',
|
SENSOR: 'Sensor',
|
||||||
TEMP_SENSOR: 'Temperatursensor',
|
TEMP_SENSOR: 'Temperatursensor',
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ const tr: Translation = {
|
|||||||
DUTY_CYCLE: 'Görev Çevrimi',
|
DUTY_CYCLE: 'Görev Çevrimi',
|
||||||
UNIT: 'ÖB',
|
UNIT: 'ÖB',
|
||||||
STARTVALUE: 'Başlangıç değeri',
|
STARTVALUE: 'Başlangıç değeri',
|
||||||
WARN_GPIO: 'Uyarı: bir GPIO atarken dikkatli olun!',
|
|
||||||
EDIT: 'Değiştir',
|
EDIT: 'Değiştir',
|
||||||
SENSOR: 'Sensör',
|
SENSOR: 'Sensör',
|
||||||
TEMP_SENSOR: 'Sıcaklık Sensörü',
|
TEMP_SENSOR: 'Sıcaklık Sensörü',
|
||||||
|
|||||||
@@ -1046,7 +1046,8 @@ const emsesp_sensordata = {
|
|||||||
s: true
|
s: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
analog_enabled: true
|
analog_enabled: true,
|
||||||
|
valid_gpio_list: [6, 11, 20, 24, 28, 31, 1, 40]
|
||||||
};
|
};
|
||||||
|
|
||||||
const activity = {
|
const activity = {
|
||||||
|
|||||||
@@ -2320,4 +2320,41 @@ uint8_t System::systemStatus() {
|
|||||||
return systemStatus_;
|
return systemStatus_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the list of valid GPIOs
|
||||||
|
std::vector<uint8_t> System::valid_gpio_list() const {
|
||||||
|
// get free gpios based on board type
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32C3
|
||||||
|
std::vector<uint8_t> valid_gpios = {11, 19, 21};
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
std::vector<uint8_t> valid_gpios = {19, 20, 22, 32, 40};
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
std::vector<uint8_t> valid_gpios = {19, 20, 22, 37, 39, 42, 48};
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32
|
||||||
|
std::vector<uint8_t> valid_gpios = {6, 11, 20, 24, 28, 31, 1, 40};
|
||||||
|
#else
|
||||||
|
std::vector<uint8_t> valid_gpios = {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// filter out GPIOs already used in application settings
|
||||||
|
for (const auto & gpio : valid_gpios) {
|
||||||
|
if (gpio == pbutton_gpio_ || gpio == led_gpio_ || gpio == dallas_gpio_ || gpio == rx_gpio_ || gpio == tx_gpio_) {
|
||||||
|
valid_gpios.erase(std::remove(valid_gpios.begin(), valid_gpios.end(), gpio), valid_gpios.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// filter out GPIOs already used in analog sensors, if enabled
|
||||||
|
if (analog_enabled_) {
|
||||||
|
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
|
||||||
|
if (std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio()) != valid_gpios.end()) {
|
||||||
|
valid_gpios.erase(std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the list of valid GPIOs
|
||||||
|
std::sort(valid_gpios.begin(), valid_gpios.end());
|
||||||
|
|
||||||
|
return valid_gpios;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ class System {
|
|||||||
void systemStatus(uint8_t status_code);
|
void systemStatus(uint8_t status_code);
|
||||||
uint8_t systemStatus();
|
uint8_t systemStatus();
|
||||||
|
|
||||||
|
std::vector<uint8_t> valid_gpio_list() const;
|
||||||
|
|
||||||
static void extractSettings(const char * filename, const char * section, JsonObject output);
|
static void extractSettings(const char * filename, const char * section, JsonObject output);
|
||||||
static bool saveSettings(const char * filename, const char * section, JsonObject input);
|
static bool saveSettings(const char * filename, const char * section, JsonObject input);
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,11 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
|||||||
root["analog_enabled"] = EMSESP::analog_enabled();
|
root["analog_enabled"] = EMSESP::analog_enabled();
|
||||||
root["platform"] = EMSESP_PLATFORM;
|
root["platform"] = EMSESP_PLATFORM;
|
||||||
|
|
||||||
|
JsonArray valid_gpio_list = root["valid_gpio_list"].to<JsonArray>();
|
||||||
|
for (const auto & gpio : EMSESP::system_.valid_gpio_list()) {
|
||||||
|
valid_gpio_list.add(gpio);
|
||||||
|
}
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user