19#ifndef SRC_SUPLA_NETWORK_HTML_CUSTOM_PARAMETER_H_
20#define SRC_SUPLA_NETWORK_HTML_CUSTOM_PARAMETER_H_
22#ifndef ARDUINO_ARCH_AVR
28#include <supla/network/html_element.h>
29#include <supla/network/web_sender.h>
30#include <supla/storage/config.h>
31#include <supla/storage/storage.h>
32#include <supla/tools.h>
47class CustomParameterTemplate :
public HtmlElement {
49 CustomParameterTemplate(
const char* paramTag,
50 const char* paramLabel,
51 T defaultValue =
static_cast<T
>(0),
52 T minValue = std::numeric_limits<T>::lowest(),
53 T maxValue = std::numeric_limits<T>::max(),
54 uint8_t decimalPlaces = 0);
56 virtual ~CustomParameterTemplate();
59 bool handleResponse(
const char* key,
const char* value)
override;
61 T getParameterValue();
62 void setParameterValue(T newValue);
66 (std::is_integral<T>::value && std::is_signed<T>::value) ||
67 std::is_floating_point<T>::value,
68 "CustomParameterTemplate supports signed integers and floating types");
70 int32_t parameterValue = 0;
72 char* label =
nullptr;
73 int32_t minStoredValue = 0;
74 int32_t maxStoredValue = 0;
75 uint8_t decimalPlaces = 0;
77 static uint8_t sanitizeDecimalPlaces(uint8_t requestedDecimalPlaces);
78 static int32_t getScaleFactor(uint8_t decimalPlaces);
79 static int32_t clampToInt32(
long double value);
81 int32_t encodeValue(T value)
const;
82 T decodeValue(int32_t value)
const;
83 void setStoredValue(int32_t newValue,
bool saveToConfig);
87CustomParameterTemplate<T>::CustomParameterTemplate(
const char* paramTag,
88 const char* paramLabel,
92 uint8_t decimalPlaces)
94decimalPlaces(sanitizeDecimalPlaces(decimalPlaces)) {
95 if (paramTag !=
nullptr) {
96 int size = strlen(paramTag);
98 tag =
new char[size + 1];
99 strncpy(tag, paramTag, size + 1);
103 if (paramLabel !=
nullptr) {
104 int size = strlen(paramLabel);
106 label =
new char[size + 1];
107 strncpy(label, paramLabel, size + 1);
111 minStoredValue = encodeValue(minValue);
112 maxStoredValue = encodeValue(maxValue);
113 if (minStoredValue > maxStoredValue) {
114 const int32_t tmp = minStoredValue;
115 minStoredValue = maxStoredValue;
116 maxStoredValue = tmp;
119 setStoredValue(encodeValue(defaultValue),
false);
123CustomParameterTemplate<T>::~CustomParameterTemplate() {
124 if (tag !=
nullptr) {
128 if (label !=
nullptr) {
135uint8_t CustomParameterTemplate<T>::sanitizeDecimalPlaces(
136 uint8_t requestedDecimalPlaces) {
137 if (std::is_integral<T>::value) {
140 return requestedDecimalPlaces > 6 ? 6 : requestedDecimalPlaces;
144int32_t CustomParameterTemplate<T>::getScaleFactor(uint8_t decimalPlaces) {
146 for (uint8_t i = 0; i < decimalPlaces; i++) {
153int32_t CustomParameterTemplate<T>::clampToInt32(
long double value) {
154 if (value >
static_cast<long double>(INT32_MAX)) {
157 if (value <
static_cast<long double>(INT32_MIN)) {
160 return static_cast<int32_t
>(value);
164int32_t CustomParameterTemplate<T>::encodeValue(T value)
const {
165 if (std::is_integral<T>::value) {
166 return clampToInt32(
static_cast<long double>(value));
169 const long double scale =
170 static_cast<long double>(getScaleFactor(decimalPlaces));
171 long double scaled =
static_cast<long double>(value) * scale;
177 return clampToInt32(scaled);
181T CustomParameterTemplate<T>::decodeValue(int32_t value)
const {
182 if (std::is_integral<T>::value) {
183 return static_cast<T
>(value);
186 return static_cast<T
>(
static_cast<long double>(value) /
187 getScaleFactor(decimalPlaces));
191void CustomParameterTemplate<T>::setStoredValue(int32_t newValue,
193 if (newValue < minStoredValue) {
194 newValue = minStoredValue;
196 if (newValue > maxStoredValue) {
197 newValue = maxStoredValue;
200 parameterValue = newValue;
202 auto cfg = Supla::Storage::ConfigInstance();
203 if (saveToConfig && cfg) {
204 cfg->setInt32(tag, parameterValue);
205 cfg->saveWithDelay(1000);
210void CustomParameterTemplate<T>::send(Supla::WebSender* sender) {
211 auto cfg = Supla::Storage::ConfigInstance();
213 int32_t storedValue = parameterValue;
214 if (cfg->getInt32(tag, &storedValue)) {
215 setStoredValue(storedValue,
false);
223 .
attr(
"type",
"number")
224 .
attr(
"step", 1, decimalPlaces)
225 .
attr(
"min", minStoredValue, decimalPlaces)
226 .
attr(
"max", maxStoredValue, decimalPlaces)
229 .
attr(
"value", parameterValue, decimalPlaces)
235bool CustomParameterTemplate<T>::handleResponse(
const char* key,
237 if (key ==
nullptr || value ==
nullptr || tag ==
nullptr ||
238 strcmp(key, tag) != 0) {
242 int32_t parsedValue = 0;
243 if (std::is_integral<T>::value) {
244 parsedValue = stringToInt(value);
246 parsedValue = floatStringToInt(value, decimalPlaces);
249 setStoredValue(parsedValue,
true);
254T CustomParameterTemplate<T>::getParameterValue() {
255 auto cfg = Supla::Storage::ConfigInstance();
257 int32_t storedValue = parameterValue;
258 if (cfg->getInt32(tag, &storedValue)) {
259 setStoredValue(storedValue,
false);
262 return decodeValue(parameterValue);
266void CustomParameterTemplate<T>::setParameterValue(T newValue) {
267 setStoredValue(encodeValue(newValue),
true);
Definition html_element.h:37
HtmlTag & attr(const char *name, const char *value)
Append a quoted HTML attribute with escaped value.
Definition web_sender.cpp:64
HtmlTag & finish()
Close the opening tag and mark it as finished.
Definition web_sender.cpp:113
This HTML Element provides numeric input in config mode.
Definition custom_parameter.h:47
Definition web_sender.h:175
void formField(Fn &&fn, const char *className="form-field")
Emit a <div class="form-field">...</div> block.
Definition web_sender.h:218
HtmlTag voidTag(const char *tagName)
Start a builder for a void HTML tag such as <input>.
Definition web_sender.h:379
void labelFor(const char *id, const char *text)
Emit a <label for="...">...</label> pair.
Definition web_sender.cpp:152