4#ifndef SRC_SUPLA_NETWORK_HTML_CUSTOM_PARAMETER_H_
5#define SRC_SUPLA_NETWORK_HTML_CUSTOM_PARAMETER_H_
7#ifndef ARDUINO_ARCH_AVR
13#include <supla/network/html_element.h>
14#include <supla/network/web_sender.h>
15#include <supla/storage/config.h>
16#include <supla/storage/storage.h>
17#include <supla/tools.h>
35 const char* paramLabel,
36 T defaultValue =
static_cast<T
>(0),
37 T minValue = std::numeric_limits<T>::lowest(),
38 T maxValue = std::numeric_limits<T>::max(),
39 uint8_t decimalPlaces = 0);
44 bool handleResponse(
const char* key,
const char* value)
override;
46 T getParameterValue();
47 void setParameterValue(T newValue);
51 (std::is_integral<T>::value && std::is_signed<T>::value) ||
52 std::is_floating_point<T>::value,
53 "CustomParameterTemplate supports signed integers and floating types");
55 int32_t parameterValue = 0;
57 char* label =
nullptr;
58 int32_t minStoredValue = 0;
59 int32_t maxStoredValue = 0;
60 uint8_t decimalPlaces = 0;
62 static uint8_t sanitizeDecimalPlaces(uint8_t requestedDecimalPlaces);
63 static int32_t getScaleFactor(uint8_t decimalPlaces);
64 static int32_t clampToInt32(
long double value);
66 int32_t encodeValue(T value)
const;
67 T decodeValue(int32_t value)
const;
68 void setStoredValue(int32_t newValue,
bool saveToConfig);
73 const char* paramLabel,
77 uint8_t decimalPlaces)
79decimalPlaces(sanitizeDecimalPlaces(decimalPlaces)) {
80 if (paramTag !=
nullptr) {
81 int size = strlen(paramTag);
83 tag =
new char[size + 1];
84 strncpy(tag, paramTag, size + 1);
88 if (paramLabel !=
nullptr) {
89 int size = strlen(paramLabel);
91 label =
new char[size + 1];
92 strncpy(label, paramLabel, size + 1);
96 minStoredValue = encodeValue(minValue);
97 maxStoredValue = encodeValue(maxValue);
98 if (minStoredValue > maxStoredValue) {
99 const int32_t tmp = minStoredValue;
100 minStoredValue = maxStoredValue;
101 maxStoredValue = tmp;
104 setStoredValue(encodeValue(defaultValue),
false);
108CustomParameterTemplate<T>::~CustomParameterTemplate() {
109 if (tag !=
nullptr) {
113 if (label !=
nullptr) {
120uint8_t CustomParameterTemplate<T>::sanitizeDecimalPlaces(
121 uint8_t requestedDecimalPlaces) {
122 if (std::is_integral<T>::value) {
125 return requestedDecimalPlaces > 6 ? 6 : requestedDecimalPlaces;
129int32_t CustomParameterTemplate<T>::getScaleFactor(uint8_t decimalPlaces) {
131 for (uint8_t i = 0; i < decimalPlaces; i++) {
138int32_t CustomParameterTemplate<T>::clampToInt32(
long double value) {
139 if (value >
static_cast<long double>(INT32_MAX)) {
142 if (value <
static_cast<long double>(INT32_MIN)) {
145 return static_cast<int32_t
>(value);
149int32_t CustomParameterTemplate<T>::encodeValue(T value)
const {
150 if (std::is_integral<T>::value) {
151 return clampToInt32(
static_cast<long double>(value));
154 const long double scale =
155 static_cast<long double>(getScaleFactor(decimalPlaces));
156 long double scaled =
static_cast<long double>(value) * scale;
162 return clampToInt32(scaled);
166T CustomParameterTemplate<T>::decodeValue(int32_t value)
const {
167 if (std::is_integral<T>::value) {
168 return static_cast<T
>(value);
171 return static_cast<T
>(
static_cast<long double>(value) /
172 getScaleFactor(decimalPlaces));
176void CustomParameterTemplate<T>::setStoredValue(int32_t newValue,
178 if (newValue < minStoredValue) {
179 newValue = minStoredValue;
181 if (newValue > maxStoredValue) {
182 newValue = maxStoredValue;
185 parameterValue = newValue;
187 auto cfg = Supla::Storage::ConfigInstance();
188 if (saveToConfig && cfg) {
189 cfg->setInt32(tag, parameterValue);
190 cfg->saveWithDelay(1000);
196 auto cfg = Supla::Storage::ConfigInstance();
198 int32_t storedValue = parameterValue;
199 if (cfg->getInt32(tag, &storedValue)) {
200 setStoredValue(storedValue,
false);
208 .
attr(
"type",
"number")
209 .
attr(
"step", 1, decimalPlaces)
210 .
attr(
"min", minStoredValue, decimalPlaces)
211 .
attr(
"max", maxStoredValue, decimalPlaces)
214 .
attr(
"value", parameterValue, decimalPlaces)
220bool CustomParameterTemplate<T>::handleResponse(
const char* key,
222 if (key ==
nullptr || value ==
nullptr || tag ==
nullptr ||
223 strcmp(key, tag) != 0) {
227 int32_t parsedValue = 0;
228 if (std::is_integral<T>::value) {
229 parsedValue = stringToInt(value);
231 parsedValue = floatStringToInt(value, decimalPlaces);
234 setStoredValue(parsedValue,
true);
239T CustomParameterTemplate<T>::getParameterValue() {
240 auto cfg = Supla::Storage::ConfigInstance();
242 int32_t storedValue = parameterValue;
243 if (cfg->getInt32(tag, &storedValue)) {
244 setStoredValue(storedValue,
false);
247 return decodeValue(parameterValue);
251void CustomParameterTemplate<T>::setParameterValue(T newValue) {
252 setStoredValue(encodeValue(newValue),
true);
255using CustomParameter = CustomParameterTemplate<int32_t>;
Definition html_element.h:22
HtmlTag & attr(const char *name, const char *value)
Append a quoted HTML attribute with escaped value.
Definition web_sender.cpp:50
HtmlTag & finish()
Close the opening tag and mark it as finished.
Definition web_sender.cpp:99
This HTML Element provides numeric input in config mode.
Definition custom_parameter.h:32
Definition web_sender.h:160
void formField(Fn &&fn, const char *className="form-field")
Emit a <div class="form-field">...</div> block.
Definition web_sender.h:204
HtmlTag voidTag(const char *tagName)
Start a builder for a void HTML tag such as <input>.
Definition web_sender.h:368
void labelFor(const char *id, const char *text)
Emit a <label for="...">...</label> pair.
Definition web_sender.cpp:138