custom min/max applied when limits read

This commit is contained in:
proddy
2026-10-17 13:39:20 +02:00
parent caedc0709c
commit 66d30570ac
17 changed files with 93 additions and 79 deletions
+1 -6
View File
@@ -23,7 +23,6 @@ import {
TextField, TextField,
ToggleButton, ToggleButton,
ToggleButtonGroup, ToggleButtonGroup,
Tooltip,
Typography Typography
} from '@mui/material'; } from '@mui/material';
@@ -295,11 +294,7 @@ const Customizations = () => {
function formatLimit(value: number | null | undefined) { function formatLimit(value: number | null | undefined) {
if (value === null) { if (value === null) {
return ( return '';
<Tooltip title={LL.CUSTOMIZATIONS_LIMITS()}>
<WarningIcon color="warning" sx={{ fontSize: 16 }} />
</Tooltip>
);
} }
return formatValue(value); return formatValue(value);
} }
@@ -4,7 +4,6 @@ import CancelIcon from '@mui/icons-material/Cancel';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done'; import DoneIcon from '@mui/icons-material/Done';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import WarningIcon from '@mui/icons-material/Warning';
import { import {
Box, Box,
Button, Button,
@@ -13,9 +12,7 @@ import {
DialogContent, DialogContent,
DialogTitle, DialogTitle,
Grid, Grid,
InputAdornment,
TextField, TextField,
Tooltip,
Typography Typography
} from '@mui/material'; } from '@mui/material';
@@ -125,15 +122,6 @@ const CustomizationsDialog = ({
onSave(next); onSave(next);
}; };
const limitAdornment = (cleared: boolean) =>
cleared ? (
<InputAdornment position="end">
<Tooltip title={LL.CUSTOMIZATIONS_LIMITS()}>
<WarningIcon color="warning" sx={{ fontSize: 16 }} />
</Tooltip>
</InputAdornment>
) : undefined;
return ( return (
<Dialog sx={dialogStyle} open={open} onClose={handleClose}> <Dialog sx={dialogStyle} open={open} onClose={handleClose}>
<DialogTitle>{`${LL.EDIT()} ${LL.ENTITY()}`}</DialogTitle> <DialogTitle>{`${LL.EDIT()} ${LL.ENTITY()}`}</DialogTitle>
@@ -180,9 +168,6 @@ const CustomizationsDialog = ({
sx={{ width: '11ch' }} sx={{ width: '11ch' }}
type="number" type="number"
onChange={updateFormValue} onChange={updateFormValue}
slotProps={{
input: { endAdornment: limitAdornment(editItem.mi === null) }
}}
/> />
</Grid> </Grid>
<Grid> <Grid>
@@ -195,9 +180,6 @@ const CustomizationsDialog = ({
sx={{ width: '11ch' }} sx={{ width: '11ch' }}
type="number" type="number"
onChange={updateFormValue} onChange={updateFormValue}
slotProps={{
input: { endAdornment: limitAdornment(editItem.ma === null) }
}}
/> />
</Grid> </Grid>
</> </>
-1
View File
@@ -134,7 +134,6 @@ const cs: Translation = {
CUSTOMIZATIONS_RESTART: 'Všechna přizpůsobení byla odstraněna. Restartování...', CUSTOMIZATIONS_RESTART: 'Všechna přizpůsobení byla odstraněna. Restartování...',
CUSTOMIZATIONS_FULL: 'Vybrané entity překročily limit. Ukládejte je postupně', CUSTOMIZATIONS_FULL: 'Vybrané entity překročily limit. Ukládejte je postupně',
CUSTOMIZATIONS_SAVED: 'Přizpůsobení uloženo', CUSTOMIZATIONS_SAVED: 'Přizpůsobení uloženo',
CUSTOMIZATIONS_LIMITS: 'Původní limity se vrátí po restartu',
CUSTOMIZATIONS_HELP_1: 'Vyberte zařízení a přizpůsobte možnosti entit nebo klikněte pro přejmenování', CUSTOMIZATIONS_HELP_1: 'Vyberte zařízení a přizpůsobte možnosti entit nebo klikněte pro přejmenování',
CUSTOMIZATIONS_HELP_2: 'označit jako oblíbené', CUSTOMIZATIONS_HELP_2: 'označit jako oblíbené',
CUSTOMIZATIONS_HELP_3: 'zakázat akci zápisu', CUSTOMIZATIONS_HELP_3: 'zakázat akci zápisu',
-1
View File
@@ -134,7 +134,6 @@ const de: Translation = {
CUSTOMIZATIONS_RESTART: 'Alle Anpassungen wurden entfernt. Neustart...', CUSTOMIZATIONS_RESTART: 'Alle Anpassungen wurden entfernt. Neustart...',
CUSTOMIZATIONS_FULL: 'Ausgewählte Entitäten haben das Limit überschritten. Bitte stapelweise speichern!', CUSTOMIZATIONS_FULL: 'Ausgewählte Entitäten haben das Limit überschritten. Bitte stapelweise speichern!',
CUSTOMIZATIONS_SAVED: 'Anpassungen gespeichert', CUSTOMIZATIONS_SAVED: 'Anpassungen gespeichert',
CUSTOMIZATIONS_LIMITS: 'Originalgrenzen gelten nach einem Neustart',
CUSTOMIZATIONS_HELP_1: 'Wählen Sie ein Gerät aus und passen Sie die Entitäten mithilfe der Optionen an', CUSTOMIZATIONS_HELP_1: 'Wählen Sie ein Gerät aus und passen Sie die Entitäten mithilfe der Optionen an',
CUSTOMIZATIONS_HELP_2: 'Als Favorit markieren', CUSTOMIZATIONS_HELP_2: 'Als Favorit markieren',
CUSTOMIZATIONS_HELP_3: 'Schreibaktion deaktivieren', CUSTOMIZATIONS_HELP_3: 'Schreibaktion deaktivieren',
-1
View File
@@ -134,7 +134,6 @@ const en: Translation = {
CUSTOMIZATIONS_RESTART: 'All customizations have been removed. Restarting...', CUSTOMIZATIONS_RESTART: 'All customizations have been removed. Restarting...',
CUSTOMIZATIONS_FULL: 'Selected entities exceeded limit. Please save in batches', CUSTOMIZATIONS_FULL: 'Selected entities exceeded limit. Please save in batches',
CUSTOMIZATIONS_SAVED: 'Customizations saved', CUSTOMIZATIONS_SAVED: 'Customizations saved',
CUSTOMIZATIONS_LIMITS: 'Original limits return after restart',
CUSTOMIZATIONS_HELP_1: 'Select a device and customize the entities options', CUSTOMIZATIONS_HELP_1: 'Select a device and customize the entities options',
CUSTOMIZATIONS_HELP_2: 'mark as favorite', CUSTOMIZATIONS_HELP_2: 'mark as favorite',
CUSTOMIZATIONS_HELP_3: 'disable write action', CUSTOMIZATIONS_HELP_3: 'disable write action',
-1
View File
@@ -134,7 +134,6 @@ const fr: Translation = {
CUSTOMIZATIONS_RESTART: 'Toutes les personnalisations ont été supprimées. Redémarrage...', CUSTOMIZATIONS_RESTART: 'Toutes les personnalisations ont été supprimées. Redémarrage...',
CUSTOMIZATIONS_FULL: 'Les entités sélectionnées ont dépassé la limite. Veuillez sauvegarder par lots', CUSTOMIZATIONS_FULL: 'Les entités sélectionnées ont dépassé la limite. Veuillez sauvegarder par lots',
CUSTOMIZATIONS_SAVED: 'Personnalisations enregistrées', CUSTOMIZATIONS_SAVED: 'Personnalisations enregistrées',
CUSTOMIZATIONS_LIMITS: "Les limites d'origine reviennent après redémarrage",
CUSTOMIZATIONS_HELP_1: 'Sélectionnez un appareil et personnalisez les options des entités ou cliquez pour renommer', CUSTOMIZATIONS_HELP_1: 'Sélectionnez un appareil et personnalisez les options des entités ou cliquez pour renommer',
CUSTOMIZATIONS_HELP_2: 'marquer comme favori', CUSTOMIZATIONS_HELP_2: 'marquer comme favori',
CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture", CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture",
-1
View File
@@ -134,7 +134,6 @@ const it: Translation = {
CUSTOMIZATIONS_RESTART: 'Tutte le personalizzazioni sono state rimosse. Riavvio ...', CUSTOMIZATIONS_RESTART: 'Tutte le personalizzazioni sono state rimosse. Riavvio ...',
CUSTOMIZATIONS_FULL: 'Le entità selezionate hanno superato il limite. Si prega di salvare in batch', CUSTOMIZATIONS_FULL: 'Le entità selezionate hanno superato il limite. Si prega di salvare in batch',
CUSTOMIZATIONS_SAVED: 'Personalizzazioni salvate', CUSTOMIZATIONS_SAVED: 'Personalizzazioni salvate',
CUSTOMIZATIONS_LIMITS: 'I limiti originali tornano dopo il riavvio',
CUSTOMIZATIONS_HELP_1: 'Seleziona un dispositivo e personalizza le opzioni delle entità o fai clic per rinominarlo', CUSTOMIZATIONS_HELP_1: 'Seleziona un dispositivo e personalizza le opzioni delle entità o fai clic per rinominarlo',
CUSTOMIZATIONS_HELP_2: 'seleziona come preferito', CUSTOMIZATIONS_HELP_2: 'seleziona come preferito',
CUSTOMIZATIONS_HELP_3: 'disabilita azione scrittura', CUSTOMIZATIONS_HELP_3: 'disabilita azione scrittura',
-1
View File
@@ -134,7 +134,6 @@ const nl: Translation = {
CUSTOMIZATIONS_RESTART: 'Alle custom profielen worden verwijderd. Herstarten...', CUSTOMIZATIONS_RESTART: 'Alle custom profielen worden verwijderd. Herstarten...',
CUSTOMIZATIONS_FULL: 'Te veel entiteiten geselecteerd. Sla op in delen aub', CUSTOMIZATIONS_FULL: 'Te veel entiteiten geselecteerd. Sla op in delen aub',
CUSTOMIZATIONS_SAVED: 'Custom aanpassingen opgeslagen', CUSTOMIZATIONS_SAVED: 'Custom aanpassingen opgeslagen',
CUSTOMIZATIONS_LIMITS: 'Originele limieten gelden na herstart',
CUSTOMIZATIONS_HELP_1: 'Selecteer een apparaat en pas de entiteiten aan door middel van de opties', CUSTOMIZATIONS_HELP_1: 'Selecteer een apparaat en pas de entiteiten aan door middel van de opties',
CUSTOMIZATIONS_HELP_2: 'Markeer als favoriet', CUSTOMIZATIONS_HELP_2: 'Markeer als favoriet',
CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit', CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit',
-1
View File
@@ -134,7 +134,6 @@ const no: Translation = {
CUSTOMIZATIONS_RESTART: 'Alle tilpasninger har blitt slettet. Restarter...', CUSTOMIZATIONS_RESTART: 'Alle tilpasninger har blitt slettet. Restarter...',
CUSTOMIZATIONS_FULL: 'Antall valgte objekter for høyt. Largre i mindre antall om gangen', CUSTOMIZATIONS_FULL: 'Antall valgte objekter for høyt. Largre i mindre antall om gangen',
CUSTOMIZATIONS_SAVED: 'Tilpasninger lagret', CUSTOMIZATIONS_SAVED: 'Tilpasninger lagret',
CUSTOMIZATIONS_LIMITS: 'Opprinnelige grenser gjelder etter omstart',
CUSTOMIZATIONS_HELP_1: 'Velg en enhet og tilpass underenheter med hjelp av alternativer eller velg å gi nytt navn', CUSTOMIZATIONS_HELP_1: 'Velg en enhet og tilpass underenheter med hjelp av alternativer eller velg å gi nytt navn',
CUSTOMIZATIONS_HELP_2: 'merk som favoritt', CUSTOMIZATIONS_HELP_2: 'merk som favoritt',
CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving', CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving',
-1
View File
@@ -134,7 +134,6 @@ const pl: BaseTranslation = {
CUSTOMIZATIONS_RESTART: 'Wszystkie personalizacje zostały usunięte. Restartuję...', CUSTOMIZATIONS_RESTART: 'Wszystkie personalizacje zostały usunięte. Restartuję...',
CUSTOMIZATIONS_FULL: 'Wybrano za dużo obiektów. Wprowadzaj zmiany w mniejszych partiach.', CUSTOMIZATIONS_FULL: 'Wybrano za dużo obiektów. Wprowadzaj zmiany w mniejszych partiach.',
CUSTOMIZATIONS_SAVED: 'Personalizacje zostały zapisane.', CUSTOMIZATIONS_SAVED: 'Personalizacje zostały zapisane.',
CUSTOMIZATIONS_LIMITS: 'Oryginalne limity wrócą po restarcie',
CUSTOMIZATIONS_HELP_1: 'Wybierz urządzenie EMS, a następnie dostosuj opcje lub kliknij na nazwie encji by tę nazwę zmienić', CUSTOMIZATIONS_HELP_1: 'Wybierz urządzenie EMS, a następnie dostosuj opcje lub kliknij na nazwie encji by tę nazwę zmienić',
CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną', CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną',
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu', CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
-1
View File
@@ -134,7 +134,6 @@ const sk: Translation = {
CUSTOMIZATIONS_RESTART: 'Ste si istí, že chcete reštartovať EMS-ESP?', CUSTOMIZATIONS_RESTART: 'Ste si istí, že chcete reštartovať EMS-ESP?',
CUSTOMIZATIONS_FULL: 'Vybrané subjekty prekročili limit. Prosím, ukladajte v dávkach', CUSTOMIZATIONS_FULL: 'Vybrané subjekty prekročili limit. Prosím, ukladajte v dávkach',
CUSTOMIZATIONS_SAVED: 'Uložené prispôsobenia', CUSTOMIZATIONS_SAVED: 'Uložené prispôsobenia',
CUSTOMIZATIONS_LIMITS: 'Pôvodné limity sa vrátia po reštarte',
CUSTOMIZATIONS_HELP_1: 'Vyberte zariadenie a prispôsobte možnosti entít alebo kliknutím premenujte', CUSTOMIZATIONS_HELP_1: 'Vyberte zariadenie a prispôsobte možnosti entít alebo kliknutím premenujte',
CUSTOMIZATIONS_HELP_2: 'označiť ako obľúbené', CUSTOMIZATIONS_HELP_2: 'označiť ako obľúbené',
CUSTOMIZATIONS_HELP_3: 'zakázať akciu zápisu', CUSTOMIZATIONS_HELP_3: 'zakázať akciu zápisu',
-1
View File
@@ -134,7 +134,6 @@ const sv: Translation = {
CUSTOMIZATIONS_RESTART: 'Alla anpassningar har raderats. Startar om...', CUSTOMIZATIONS_RESTART: 'Alla anpassningar har raderats. Startar om...',
CUSTOMIZATIONS_FULL: 'För många valda enheter. Vänligen spara ett mindre antal åt gången.', CUSTOMIZATIONS_FULL: 'För många valda enheter. Vänligen spara ett mindre antal åt gången.',
CUSTOMIZATIONS_SAVED: 'Anpassningarna är sparade', CUSTOMIZATIONS_SAVED: 'Anpassningarna är sparade',
CUSTOMIZATIONS_LIMITS: 'Originalgränserna gäller efter omstart',
CUSTOMIZATIONS_HELP_1: 'Välj en enhet och anpassa entiteter med hjälp av alternativen', CUSTOMIZATIONS_HELP_1: 'Välj en enhet och anpassa entiteter med hjälp av alternativen',
CUSTOMIZATIONS_HELP_2: 'Favorit', CUSTOMIZATIONS_HELP_2: 'Favorit',
CUSTOMIZATIONS_HELP_3: 'Skrivskyddad', CUSTOMIZATIONS_HELP_3: 'Skrivskyddad',
-1
View File
@@ -134,7 +134,6 @@ const tr: Translation = {
CUSTOMIZATIONS_RESTART: 'Bütün özelleştirmeler kaldırıldı. Yeniden başlatılıyor...', CUSTOMIZATIONS_RESTART: 'Bütün özelleştirmeler kaldırıldı. Yeniden başlatılıyor...',
CUSTOMIZATIONS_FULL: 'Seçilen varlıklar sınırı aşmaktadır. Lütfen parçalar halinde kaydedin', CUSTOMIZATIONS_FULL: 'Seçilen varlıklar sınırı aşmaktadır. Lütfen parçalar halinde kaydedin',
CUSTOMIZATIONS_SAVED: 'Özelleştirmeler kaydedildi', CUSTOMIZATIONS_SAVED: 'Özelleştirmeler kaydedildi',
CUSTOMIZATIONS_LIMITS: 'Orijinal sınırlar yeniden başlatınca döner',
CUSTOMIZATIONS_HELP_1: 'Bir cihaz seçip varlıkların seçeneklerini özelleştirin veya yeniden adlandırmak için tıklayın', CUSTOMIZATIONS_HELP_1: 'Bir cihaz seçip varlıkların seçeneklerini özelleştirin veya yeniden adlandırmak için tıklayın',
CUSTOMIZATIONS_HELP_2: 'favori olarak işaretle', CUSTOMIZATIONS_HELP_2: 'favori olarak işaretle',
CUSTOMIZATIONS_HELP_3: 'yazma işlemini devre dışı bırak', CUSTOMIZATIONS_HELP_3: 'yazma işlemini devre dışı bırak',
+26 -12
View File
@@ -877,7 +877,6 @@ void EMSdevice::set_minmax(const void * value_p, int16_t min, uint32_t max) {
if (dv.value_p == value_p) { if (dv.value_p == value_p) {
dv.min = min; dv.min = min;
dv.max = max; dv.max = max;
dv.set_custom_minmax(); // custom priority
return; return;
} }
} }
@@ -1340,6 +1339,7 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
// check the masks // check the masks
uint8_t current_mask = dv.state >> 4; uint8_t current_mask = dv.state >> 4;
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
bool had_limit = dv.custom_fullname().find('>') != std::string::npos || dv.custom_fullname().find('<') != std::string::npos;
// if it's a new mask, reconfigure HA // if it's a new mask, reconfigure HA
if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) { if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) {
@@ -1358,14 +1358,19 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
dv.set_custom_fullname(""); dv.set_custom_fullname("");
} }
auto min = dv.min; // Climate discovery reads its own min/max. selRoomTemp keeps the register limits.
auto max = dv.max; // A custom range is copied across; clearing it restores the limits haclimate was registered with (5..30).
if (Mqtt::ha_enabled() && dv.tag <= DeviceValueTAG::TAG_HC8 && !strcmp(dv.short_name, FL_(selRoomTemp)[0])) {
// set the min / max int16_t eff_min = dv.min;
dv.set_custom_minmax(); uint32_t eff_max = dv.max;
bool min_custom = false;
if (Mqtt::ha_enabled() && dv.tag <= DeviceValueTAG::TAG_HC8 && !strcmp(dv.short_name, FL_(selRoomTemp)[0]) && (min != dv.min || max != dv.max)) { bool max_custom = false;
set_climate_minmax(dv.tag, dv.min, dv.max); dv.apply_custom_minmax(eff_min, eff_max, &min_custom, &max_custom);
if (min_custom || max_custom) {
set_climate_minmax(dv.tag, eff_min, eff_max);
} else if (had_limit) {
set_climate_minmax(dv.tag, 5, 30);
}
} }
return; return;
@@ -2218,16 +2223,24 @@ bool EMSdevice::generate_values(JsonObject output, const int8_t tag_filter, cons
// check for value outside min/max range and adapt the limits to avoid HA complains // check for value outside min/max range and adapt the limits to avoid HA complains
// Should this also check for api output? // Should this also check for api output?
if ((output_target == OUTPUT_TARGET::MQTT) && (dv.min != 0 || dv.max != 0)) { // Only the register limits are widened. A custom limit stays in the name so a reset can restore the original.
{
int16_t eff_min = dv.min;
uint32_t eff_max = dv.max;
bool min_custom = false;
bool max_custom = false;
dv.apply_custom_minmax(eff_min, eff_max, &min_custom, &max_custom);
if ((output_target == OUTPUT_TARGET::MQTT) && (eff_min != 0 || eff_max != 0)) {
int v = Helpers::atoint(val); int v = Helpers::atoint(val);
if (fahrenheit) { if (fahrenheit) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
} }
if (v < dv.min) { if (v < eff_min && !min_custom) {
dv.min = v; dv.min = v;
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
} else if (v > 0 && (uint32_t)v > dv.max) { } else if (v > 0 && (uint32_t)v > eff_max && !max_custom) {
dv.max = v; dv.max = v;
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
} }
@@ -2235,6 +2248,7 @@ bool EMSdevice::generate_values(JsonObject output, const int8_t tag_filter, cons
} }
} }
} }
}
return has_values; return has_values;
} }
+48 -20
View File
@@ -66,9 +66,6 @@ DeviceValue::DeviceValue(uint8_t device_type,
custom_fullname_ = std::make_unique<std::string>(custom_fullname); custom_fullname_ = std::make_unique<std::string>(custom_fullname);
} }
// set the min/max (reads back the custom name set above)
set_custom_minmax();
/* /*
#ifdef EMSESP_STANDALONE #ifdef EMSESP_STANDALONE
// only added for debugging // only added for debugging
@@ -296,11 +293,15 @@ bool DeviceValue::has_tag() const {
bool DeviceValue::get_min_max(int16_t & dv_set_min, uint32_t & dv_set_max) { bool DeviceValue::get_min_max(int16_t & dv_set_min, uint32_t & dv_set_max) {
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0; uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
// if we have individual limits set already, just do the conversion // Register limits stay in min/max. Custom limits, if any, are applied only here.
// limits are not scaled with num operator and temperatures are °C // limits are not scaled with num operator and temperatures are °C
if (min != 0 || max != 0) { int16_t eff_min = min;
dv_set_min = Helpers::transformNumFloat(min, 0, fahrenheit); uint32_t eff_max = max;
dv_set_max = Helpers::transformNumFloat(max, 0, fahrenheit); apply_custom_minmax(eff_min, eff_max);
if (eff_min != 0 || eff_max != 0) {
dv_set_min = Helpers::transformNumFloat(eff_min, 0, fahrenheit);
dv_set_max = Helpers::transformNumFloat(eff_max, 0, fahrenheit);
return true; return true;
} }
@@ -350,8 +351,8 @@ bool DeviceValue::get_min_max(int16_t & dv_set_min, uint32_t & dv_set_max) {
return false; // nothing changed, not supported return false; // nothing changed, not supported
} }
// extract custom min from custom_fullname // extract custom min from custom_fullname, in °C. Does not range-check against the register limits.
bool DeviceValue::get_custom_min(int16_t & val) { bool DeviceValue::get_custom_min(int16_t & val) const {
const auto & cf = custom_fullname(); const auto & cf = custom_fullname();
auto min_pos = cf.find('>'); auto min_pos = cf.find('>');
bool has_min = (min_pos != std::string::npos); bool has_min = (min_pos != std::string::npos);
@@ -362,18 +363,14 @@ bool DeviceValue::get_custom_min(int16_t & val) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
} }
if (max > 0 && v > 0 && (uint32_t)v > max) {
return false;
}
val = v; val = v;
} }
return has_min; return has_min;
} }
// extract custom max from custom_fullname // extract custom max from custom_fullname, in °C. Does not range-check against the register limits.
bool DeviceValue::get_custom_max(uint32_t & val) { bool DeviceValue::get_custom_max(uint32_t & val) const {
const auto & cf = custom_fullname(); const auto & cf = custom_fullname();
auto max_pos = cf.find('<'); auto max_pos = cf.find('<');
bool has_max = (max_pos != std::string::npos); bool has_max = (max_pos != std::string::npos);
@@ -384,7 +381,7 @@ bool DeviceValue::get_custom_max(uint32_t & val) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
} }
if (v < 0 || v < (int32_t)min) { if (v < 0) {
return false; return false;
} }
@@ -394,10 +391,41 @@ bool DeviceValue::get_custom_max(uint32_t & val) {
return has_max; return has_max;
} }
// sets min max to stored custom values (if set) // Overlay custom limits onto copies of the register min/max. A custom min is checked against
void DeviceValue::set_custom_minmax() { // the custom max when both are set, so a range outside the register limits is still accepted.
get_custom_min(min); void DeviceValue::apply_custom_minmax(int16_t & eff_min, uint32_t & eff_max, bool * min_custom, bool * max_custom) const {
get_custom_max(max); int16_t cmin = 0;
uint32_t cmax = 0;
bool has_cmin = get_custom_min(cmin);
bool has_cmax = get_custom_max(cmax);
if (has_cmin) {
uint32_t bound = has_cmax ? cmax : eff_max;
if (bound > 0 && cmin > 0 && (uint32_t)cmin > bound) {
has_cmin = false;
}
}
if (has_cmax) {
int32_t bound = has_cmin ? cmin : eff_min;
if ((int32_t)cmax < bound) {
has_cmax = false;
}
}
if (has_cmin) {
eff_min = cmin;
}
if (has_cmax) {
eff_max = cmax;
}
if (min_custom) {
*min_custom = has_cmin;
}
if (max_custom) {
*max_custom = has_cmax;
}
} }
// raw stored custom name (empty string if none was set) // raw stored custom name (empty string if none was set)
+6 -3
View File
@@ -218,9 +218,12 @@ class DeviceValue {
bool has_tag() const; bool has_tag() const;
bool get_min_max(int16_t & dv_set_min, uint32_t & dv_set_max); bool get_min_max(int16_t & dv_set_min, uint32_t & dv_set_max);
void set_custom_minmax(); // Overlay a custom >min/<max from the name onto eff_min/eff_max.
bool get_custom_min(int16_t & val); // The stored register limits (min/max) are left unchanged.
bool get_custom_max(uint32_t & val); // min_custom/max_custom report whether that side came from the custom name.
void apply_custom_minmax(int16_t & eff_min, uint32_t & eff_max, bool * min_custom = nullptr, bool * max_custom = nullptr) const;
bool get_custom_min(int16_t & val) const;
bool get_custom_max(uint32_t & val) const;
std::string get_custom_fullname() const; std::string get_custom_fullname() const;
std::string get_fullname() const; std::string get_fullname() const;
static std::string get_name(const std::string & entity); static std::string get_name(const std::string & entity);
+4 -1
View File
@@ -458,7 +458,10 @@ int Modbus::getRegisterCount(const DeviceValue & dv) {
case DeviceValue::CMD: { case DeviceValue::CMD: {
// calculate a sensible register size from min, max and numeric_operator // calculate a sensible register size from min, max and numeric_operator
uint32_t num_values = std::max(dv.max, (uint32_t)abs(dv.min)); int16_t eff_min = dv.min;
uint32_t eff_max = dv.max;
dv.apply_custom_minmax(eff_min, eff_max);
uint32_t num_values = std::max(eff_max, (uint32_t)abs(eff_min));
int num_registers = 0; int num_registers = 0;
if (num_values < (1L << 16)) if (num_values < (1L << 16))