Commit 8c4fc341 authored by Eric Duminil's avatar Eric Duminil
Browse files

IotWebConf in src, not in platformio

parent 9d0a0e38
/**
* IotWebConfParameter.h -- IotWebConf is an ESP8266/ESP32
* non blocking WiFi/AP web configuration library for Arduino.
* https://github.com/prampec/IotWebConf
*
* Copyright (C) 2020 Balazs Kelemen <prampec+arduino@gmail.com>
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#ifndef IotWebConfParameter_h
#define IotWebConfParameter_h
#include <Arduino.h>
#include <functional>
#include <IotWebConfSettings.h>
#include <IotWebConfWebServerWrapper.h>
#ifdef IOTWEBCONF_ENABLE_JSON
# include <ArduinoJson.h>
#endif
const char IOTWEBCONF_HTML_FORM_GROUP_START[] PROGMEM =
"<fieldset id='{i}'><legend>{b}</legend>\n";
const char IOTWEBCONF_HTML_FORM_GROUP_END[] PROGMEM =
"</fieldset>\n";
const char IOTWEBCONF_HTML_FORM_PARAM[] PROGMEM =
"<div class='{s}'><label for='{i}'>{b}</label><input type='{t}' id='{i}' "
"name='{i}' {l} placeholder='{p}' value='{v}' {c}/>"
"<div class='em'>{e}</div></div>\n";
const char IOTWEBCONF_HTML_FORM_SELECT_PARAM[] PROGMEM =
"<div class='{s}'><label for='{i}'>{b}</label><select id='{i}' "
"name='{i}' {c}/>\n{o}"
"</select><div class='em'>{e}</div></div>\n";
const char IOTWEBCONF_HTML_FORM_OPTION[] PROGMEM =
"<option value='{v}'{s}>{n}</option>\n";
namespace iotwebconf
{
typedef struct SerializationData
{
byte* data;
int length;
} SerializationData;
class ConfigItem
{
public:
bool visible = true;
const char* getId() { return this->_id; }
/**
* Calculate the size of bytes should be stored in the EEPROM.
*/
virtual int getStorageSize() = 0;
/**
* On initial startup (when no data was saved), it may be required to apply a default value
* to the parameter.
*/
virtual void applyDefaultValue() = 0;
/**
* Save data.
* @doStore - A method is passed as a parameter, that will performs the actual EEPROM access.
* The argument 'serializationData' of this referenced method should be pre-filled with
* the size and the serialized data before calling the method.
*/
virtual void storeValue(std::function<void(SerializationData* serializationData)> doStore) = 0;
/**
* Load data.
* @doLoad - A method is passed as a parameter, that will performs the actual EEPROM access.
* The argument 'serializationData' of this referenced method should be pre-filled with
* the size of the expected data, and the data buffer should be allocated with this size.
* The doLoad will fill the data from the EEPROM.
*/
virtual void loadValue(std::function<void(SerializationData* serializationData)> doLoad) = 0;
/**
* This method will create the HTML form item for the config portal.
*
* @dataArrived - True if there was a form post, where (some) form
* data arrived from the client.
* @webRequestWrapper - The webRequestWrapper, that will send the rendered content to the client.
* The webRequestWrapper->sendContent() method should be used in the implementations.
*/
virtual void renderHtml(bool dataArrived, WebRequestWrapper* webRequestWrapper) = 0;
/**
* New value arrived from the form post. The value should be stored in the
* in this config item.
*
* @webRequestWrapper - The webRequestWrapper, that will send the rendered content to the client.
* The webRequestWrapper->hasArg() and webRequestWrapper->arg() methods should be used in the
* implementations.
*/
virtual void update(WebRequestWrapper* webRequestWrapper) = 0;
/**
* Before validating the form post, it is required to clear previous error messages.
*/
virtual void clearErrorMessage() = 0;
/**
* This method should display information to Serial containing the parameter
* ID and the current value of the parameter (if it is confidential).
* Will only be called if debug is enabled.
*/
virtual void debugTo(Stream* out) = 0;
#ifdef IOTWEBCONF_ENABLE_JSON
/**
*
*/
virtual void loadFromJson(JsonObject jsonObject) = 0;
#endif
protected:
ConfigItem(const char* id) { this->_id = id; };
private:
const char* _id = 0;
ConfigItem* _parentItem = nullptr;
ConfigItem* _nextItem = nullptr;
friend class ParameterGroup; // Allow ParameterGroup to access _nextItem.
};
class ParameterGroup : public ConfigItem
{
public:
ParameterGroup(const char* id, const char* label = nullptr);
void addItem(ConfigItem* configItem);
const char *label;
void applyDefaultValue() override;
#ifdef IOTWEBCONF_ENABLE_JSON
virtual void loadFromJson(JsonObject jsonObject) override;
#endif
protected:
int getStorageSize() override;
void storeValue(std::function<void(
SerializationData* serializationData)> doStore) override;
void loadValue(std::function<void(
SerializationData* serializationData)> doLoad) override;
void renderHtml(bool dataArrived, WebRequestWrapper* webRequestWrapper) override;
void update(WebRequestWrapper* webRequestWrapper) override;
void clearErrorMessage() override;
void debugTo(Stream* out) override;
/**
* One can override this method in case a specific HTML template is required
* for a group.
*/
virtual String getStartTemplate() { return FPSTR(IOTWEBCONF_HTML_FORM_GROUP_START); };
/**
* One can override this method in case a specific HTML template is required
* for a group.
*/
virtual String getEndTemplate() { return FPSTR(IOTWEBCONF_HTML_FORM_GROUP_END); };
ConfigItem* _firstItem = nullptr;
ConfigItem* getNextItemOf(ConfigItem* parent) { return parent->_nextItem; };
friend class IotWebConf; // Allow IotWebConf to access protected members.
private:
};
/**
* Parameters is a configuration item of the config portal.
* The parameter will have its input field on the configuration page,
* and the provided value will be saved to the EEPROM.
*/
class Parameter : public ConfigItem
{
public:
/**
* Create a parameter for the config portal.
*
* @label - Displayable label at the config portal.
* @id - Identifier used for HTTP queries and as configuration key. Must not
* contain spaces nor other special characters.
* @valueBuffer - Configuration value will be loaded to this buffer from the
* EEPROM.
* @length - The buffer should have a length provided here.
* @defaultValue - Defalt value set on startup, when no configuration ever saved
* with the current config-version.
*/
Parameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* defaultValue = nullptr);
const char* label;
char* valueBuffer;
const char* defaultValue;
const char* errorMessage;
int getLength() { return this->_length; }
void applyDefaultValue() override;
#ifdef IOTWEBCONF_ENABLE_JSON
virtual void loadFromJson(JsonObject jsonObject) override;
#endif
protected:
// Overrides
int getStorageSize() override;
void storeValue(std::function<void(SerializationData* serializationData)> doStore) override;
void loadValue(std::function<void(SerializationData* serializationData)> doLoad) override;
virtual void update(WebRequestWrapper* webRequestWrapper) override;
virtual void update(String newValue) = 0;
void clearErrorMessage() override;
private:
int _length;
};
///////////////////////////////////////////////////////////////////////////////
/**
* TexParameters is to store text based parameters.
*/
class TextParameter : public Parameter
{
public:
/**
* Create a text parameter for the config portal.
*
* @placeholder (optional) - Text appear in an empty input box.
* @customHtml (optional) - The text of this parameter will be added into
* the HTML INPUT field.
* (See Parameter for arguments!)
*/
TextParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* defaultValue = nullptr,
const char* placeholder = nullptr,
const char* customHtml = nullptr);
/**
* This variable is meant to store a value that is displayed in an empty
* (not filled) field.
*/
const char* placeholder;
/**
* Usually this variable is used when rendering the form input field
* so one can customize the rendered outcome of this particular item.
*/
const char* customHtml;
protected:
virtual String renderHtml(
bool dataArrived, bool hasValueFromPost, String valueFromPost);
// Overrides
virtual void renderHtml(bool dataArrived, WebRequestWrapper* webRequestWrapper) override;
virtual void update(String newValue) override;
virtual void debugTo(Stream* out) override;
/**
* One can override this method in case a specific HTML template is required
* for a parameter.
*/
virtual String getHtmlTemplate() { return FPSTR(IOTWEBCONF_HTML_FORM_PARAM); };
/**
* Renders a standard HTML form INPUT.
* @type - The type attribute of the html input field.
*/
virtual String renderHtml(const char* type, bool hasValueFromPost, String valueFromPost);
private:
friend class IotWebConf;
friend class WifiParameterGroup;
};
///////////////////////////////////////////////////////////////////////////////
/**
* The Password parameter has a special handling, as the value will be
* overwritten in the EEPROM only if value was provided on the config portal.
* Because of this logic, "password" type field with length more then
* IOTWEBCONF_PASSWORD_LEN characters are not supported.
*/
class PasswordParameter : public TextParameter
{
public:
/**
* Create a password parameter for the config portal.
*
* (See TextParameter for arguments!)
*/
PasswordParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* defaultValue = nullptr,
const char* placeholder = nullptr,
const char* customHtml = "ondblclick=\"pw(this.id)\"");
protected:
// Overrides
virtual String renderHtml(
bool dataArrived, bool hasValueFromPost, String valueFromPost) override;
virtual void update(String newValue) override;
virtual void debugTo(Stream* out) override;
private:
friend class IotWebConf;
friend class WifiParameterGroup;
};
///////////////////////////////////////////////////////////////////////////////
/**
* This is just a text parameter, that is rendered with type 'number'.
*/
class NumberParameter : public TextParameter
{
public:
/**
* Create a numeric parameter for the config portal.
*
* (See TextParameter for arguments!)
*/
NumberParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* defaultValue = nullptr,
const char* placeholder = nullptr,
const char* customHtml = nullptr);
protected:
// Overrides
virtual String renderHtml(
bool dataArrived, bool hasValueFromPost, String valueFromPost) override;
private:
friend class IotWebConf;
};
///////////////////////////////////////////////////////////////////////////////
/**
* Checkbox parameter is represended as a text parameter but has a special
* handling. As the value is either empty or has the word "selected".
* Note, that form post will not send value if checkbox was not selected.
*/
class CheckboxParameter : public TextParameter
{
public:
/**
* Create a checkbox parameter for the config portal.
*
* (See TextParameter for arguments!)
*/
CheckboxParameter(
const char* label, const char* id, char* valueBuffer, int length,
bool defaultValue = false);
bool isChecked() { return strncmp(this->valueBuffer, "selected", this->getLength()) == 0; }
protected:
// Overrides
virtual String renderHtml(
bool dataArrived, bool hasValueFromPost, String valueFromPost) override;
virtual void update(WebRequestWrapper* webRequestWrapper) override;
private:
friend class IotWebConf;
bool _checked;
const char* _checkedStr = "checked='checked'";
};
///////////////////////////////////////////////////////////////////////////////
/**
* Options parameter is a structure, that handles multiple values when redering
* the HTML representation.
*/
class OptionsParameter : public TextParameter
{
public:
/**
* @optionValues - List of values to choose from with, where each value
* can have a maximal size of 'length'. Contains 'optionCount' items.
* @optionNames - List of names to render for the values, where each
* name can have a maximal size of 'nameLength'. Contains 'optionCount'
* items.
* @optionCount - Size of both 'optionValues' and 'optionNames' lists.
* @nameLength - Size of any item in optionNames list.
* (See TextParameter for arguments!)
*/
OptionsParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* optionValues, const char* optionNames, size_t optionCount, size_t nameLength,
const char* defaultValue = nullptr);
protected:
const char* _optionValues;
const char* _optionNames;
size_t _optionCount;
size_t _nameLength;
private:
friend class IotWebConf;
};
///////////////////////////////////////////////////////////////////////////////
/**
* Select parameter is an option parameter, that rendered as HTML SELECT.
* Basically it is a dropdown combobox.
*/
class SelectParameter : public OptionsParameter
{
public:
/**
* Create a select parameter for the config portal.
*
* (See OptionsParameter for arguments!)
*/
SelectParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* optionValues, const char* optionNames, size_t optionCount, size_t namesLenth,
const char* defaultValue = nullptr);
protected:
// Overrides
virtual String renderHtml(
bool dataArrived, bool hasValueFromPost, String valueFromPost) override;
private:
friend class IotWebConf;
};
/**
* This class is here just to make some nice indents on debug output
* for group tree.
*/
class PrefixStreamWrapper : public Stream
{
public:
PrefixStreamWrapper(
Stream* originalStream,
std::function<size_t(Stream* stream)> prefixWriter);
size_t write(uint8_t) override;
size_t write(const uint8_t *buffer, size_t size) override;
int available() override { return _originalStream->available(); };
int read() override { return _originalStream->read(); };
int peek() override { return _originalStream->peek(); };
void flush() override { return _originalStream->flush(); };
private:
Stream* _originalStream;
std::function<size_t(Stream* stream)> _prefixWriter;
bool _newLine = true;
size_t checkNewLine();
};
} // end namespace
#endif
/**
* IotWebConfSettings.h -- IotWebConf is an ESP8266/ESP32
* non blocking WiFi/AP web configuration library for Arduino.
* https://github.com/prampec/IotWebConf
*
* Copyright (C) 2020 Balazs Kelemen <prampec+arduino@gmail.com>
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#ifndef IotWebConfSettings_h
#define IotWebConfSettings_h
// -- We might want to place the config in the EEPROM in an offset.
#ifndef IOTWEBCONF_CONFIG_START
# define IOTWEBCONF_CONFIG_START 0
#endif
// -- Maximal length of any string used in IotWebConfig configuration (e.g.
// ssid).
#ifndef IOTWEBCONF_WORD_LEN
# define IOTWEBCONF_WORD_LEN 33
#endif
// -- Maximal length of password used in IotWebConfig configuration.
#ifndef IOTWEBCONF_PASSWORD_LEN
# define IOTWEBCONF_PASSWORD_LEN 33
#endif
// -- IotWebConf tries to connect to the local network for an amount of time
// before falling back to AP mode.
#ifndef IOTWEBCONF_DEFAULT_WIFI_CONNECTION_TIMEOUT_MS
# define IOTWEBCONF_DEFAULT_WIFI_CONNECTION_TIMEOUT_MS 30000
#endif
// -- Thing will stay in AP mode for an amount of time on boot, before retrying
// to connect to a WiFi network.
#ifndef IOTWEBCONF_DEFAULT_AP_MODE_TIMEOUT_SECS
# define IOTWEBCONF_DEFAULT_AP_MODE_TIMEOUT_SECS "30"
#endif
// -- mDNS should allow you to connect to this device with a hostname provided
// by the device. E.g. mything.local
// (This is not very likely to work, and MDNS is not very well documented.)
#ifndef IOTWEBCONF_CONFIG_DONT_USE_MDNS
# define IOTWEBCONF_CONFIG_USE_MDNS 80
#endif
// -- Logs progress information to Serial if enabled.
#ifndef IOTWEBCONF_DEBUG_DISABLED
# define IOTWEBCONF_DEBUG_TO_SERIAL
#endif
// -- Logs passwords to Serial if enabled.
//#define IOTWEBCONF_DEBUG_PWD_TO_SERIAL
// -- Helper define for serial debug
#ifdef IOTWEBCONF_DEBUG_TO_SERIAL
# define IOTWEBCONF_DEBUG_LINE(MSG) Serial.println(MSG)
#else
# define IOTWEBCONF_DEBUG_LINE(MSG)
#endif
// -- EEPROM config starts with a special prefix of length defined here.
#ifndef IOTWEBCONF_CONFIG_VERSION_LENGTH
# define IOTWEBCONF_CONFIG_VERSION_LENGTH 4
#endif
#ifndef IOTWEBCONF_DNS_PORT
# define IOTWEBCONF_DNS_PORT 53
#endif
#endif
\ No newline at end of file
This diff is collapsed.
/**
* IotWebConfTParameter.h -- IotWebConf is an ESP8266/ESP32
* non blocking WiFi/AP web configuration library for Arduino.
* https://github.com/prampec/IotWebConf
*
* Copyright (C) 2021 Balazs Kelemen <prampec+arduino@gmail.com>
* rovo89
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#ifndef IotWebConfTParameterBuilder_h
#define IotWebConfTParameterBuilder_h
#include <IotWebConfTParameter.h>
namespace iotwebconf
{
template <typename ParamType> class Builder;
template <typename ParamType>
class AbstractBuilder
{
public:
AbstractBuilder(const char* id) : _id(id) { };
virtual ParamType build() const
{
ParamType instance = std::move(
ParamType(this->_id, this->_label, this->_defaultValue));
this->apply(&instance);
return instance;
}
Builder<ParamType>& label(const char* label)
{ this->_label = label; return static_cast<Builder<ParamType>&>(*this); }
Builder<ParamType>& defaultValue(typename ParamType::DefaultValueType defaultValue)
{ this->_defaultValue = defaultValue; return static_cast<Builder<ParamType>&>(*this); }
protected:
virtual ParamType* apply(ParamType* instance) const
{
return instance;
}
const char* _label;
const char* _id;
typename ParamType::DefaultValueType _defaultValue;
};
template <typename ParamType>
class Builder : public AbstractBuilder<ParamType>
{
public:
Builder(const char* id) : AbstractBuilder<ParamType>(id) { };
};
///////////////////////////////////////////////////////////////////////////
template <typename ValueType, typename ParamType>
class PrimitiveBuilder :
public AbstractBuilder<ParamType>
{
public:
PrimitiveBuilder<ValueType, ParamType>(const char* id) :
AbstractBuilder<ParamType>(id) { };
Builder<ParamType>& min(ValueType min) { this->_minDefined = true; this->_min = min; return static_cast<Builder<ParamType>&>(*this); }
Builder<ParamType>& max(ValueType max) { this->_maxDefined = true; this->_max = max; return static_cast<Builder<ParamType>&>(*this); }
Builder<ParamType>& step(ValueType step) { this->_step = step; return static_cast<Builder<ParamType>&>(*this); }
Builder<ParamType>& placeholder(const char* placeholder) { this->_placeholder = placeholder; return static_cast<Builder<ParamType>&>(*this); }
protected:
virtual ParamType* apply(
ParamType* instance) const override
{
if (this->_minDefined)
{
instance->setMin(this->_min);
}
if (this->_maxDefined)
{
instance->setMax(this->_max);
}
instance->setStep(this->_step);
instance->setPlaceholder(this->_placeholder);
return instance;
}
bool _minDefined = false;
bool _maxDefined = false;
ValueType _min;
ValueType _max;
ValueType _step = 0;
const char* _placeholder = nullptr;
};
template <typename ValueType, int base>
class Builder<IntTParameter<ValueType, base>> :
public PrimitiveBuilder<ValueType, IntTParameter<ValueType, base>>
{
public:
Builder<IntTParameter<ValueType, base>>(const char* id) :
PrimitiveBuilder<ValueType, IntTParameter<ValueType, base>>(id) { };
};
template <typename ValueType, int base>
class Builder<UIntTParameter<ValueType, base>> :
public PrimitiveBuilder<ValueType, UIntTParameter<ValueType, base>>
{
public:
Builder<UIntTParameter<ValueType, base>>(const char* id) :
PrimitiveBuilder<ValueType, UIntTParameter<ValueType, base>>(id) { };
};
template <>
class Builder<FloatTParameter> :
public PrimitiveBuilder<float, FloatTParameter>
{
public:
Builder<FloatTParameter>(const char* id) :
PrimitiveBuilder<float, FloatTParameter>(id) { };
};
template <size_t len>
class Builder<SelectTParameter<len>> :
public AbstractBuilder<SelectTParameter<len>>
{
public:
Builder<SelectTParameter<len>>(const char* id) :
AbstractBuilder<SelectTParameter<len>>(id) { };
virtual SelectTParameter<len> build() const override
{
return SelectTParameter<len>(
this->_id, this->_label, this->_defaultValue,
this->_optionValues, this->_optionNames,
this->_optionCount, this->_nameLength);
}
Builder<SelectTParameter<len>>& optionValues(const char* optionValues)
{ this->_optionValues = optionValues; return *this; }
Builder<SelectTParameter<len>>& optionNames(const char* optionNames)
{ this->_optionNames = optionNames; return *this; }
Builder<SelectTParameter<len>>& optionCount(size_t optionCount)
{ this->_optionCount = optionCount; return *this; }
Builder<SelectTParameter<len>>& nameLength(size_t nameLength)
{ this->_nameLength = nameLength; return *this; }
protected:
virtual SelectTParameter<len>* apply(
SelectTParameter<len>* instance) const override
{
instance->setOptionValues(this->_optionValues);
instance->setOptionNames(this->_optionNames);
instance->setOptionCount(this->_optionCount);
instance->setNameLength(this->_nameLength);
return instance;
}
private:
const char* _optionValues;
const char* _optionNames;
size_t _optionCount;
size_t _nameLength;
};
} // End namespace
#endif
/**
* IotWebConfUsing.h -- IotWebConf is an ESP8266/ESP32
* non blocking WiFi/AP web configuration library for Arduino.
* https://github.com/prampec/IotWebConf
*
* Copyright (C) 2020 Balazs Kelemen <prampec+arduino@gmail.com>
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#ifndef IotWebConfUsing_h
#define IotWebConfUsing_h
// This "using" lines are just aliases, and should avoided.
using IotWebConfParameterGroup = iotwebconf::ParameterGroup;
using IotWebConfTextParameter = iotwebconf::TextParameter;
using IotWebConfPasswordParameter = iotwebconf::PasswordParameter;
using IotWebConfNumberParameter = iotwebconf::NumberParameter;
using IotWebConfCheckboxParameter = iotwebconf::CheckboxParameter;
using IotWebConfSelectParameter = iotwebconf::SelectParameter;
#endif
\ No newline at end of file
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment