prampec / IotWebConf

ESP8266/ESP32 non-blocking WiFi/AP web configuration Arduino library
MIT License
523 stars 140 forks source link

is IotWebConf the right tool for configuring my little device? #245

Open garubi opened 2 years ago

garubi commented 2 years ago

I have a use case different from the "main" purpose of IotWebConf and I'm wondering if you folks can provide some suggestion.

context: I built a little BLE page turner based on ESP32. It's a very simple device: it act as a Bluetooth keyboard, it has 2 buttons and it sends keystrokes each time a button is pressed. (commercial example: https://www.airturn.com/products/categories/bluetooth-pedals ). I'm using it since june 2021 and it's ok.

aim: Now I would like to use IotWebConf to implement the ability for the user to connect via WiFi to the pedalboard to configure on its own which keystroke to send (now they are hardcoded in the code).

The device doesn't need to connect to any network, it just have to come up as soft Access Point, let the user choose one named keystroke from two <select> inputs ("Custom parameter", in the IotWebConfig lingo) and save the configuration. (And of course the user could change the device name and access point password).

first question: Do you think IotWebConf is the right tool to easily implement such a feature? If not do you know of any other tool that can provide a quick solution?

my attempt and main question: I basically had it working but when I save the config page, the values are stored but obviously it complains that I "have to provide wifi settings to continue" because -since I don't need to connect to a network- I don't provide any SSID and password.

Is there a way to avoid this issue?

Thank you very much in advance Stefano

Here is the relevant part of my code.

#include <IotWebConf.h>
#include <IotWebConfUsing.h> 
#include <BleKeyboard.h>
#include <Pangodream_18650_CL.h>
#include <Bounce2.h>

// Pin per i Pulsanti
const byte PEDALNEXT_PIN = 21;
const byte PEDALPREV_PIN = 23;

// Led
const byte PEDALNEXT_LED = LED_BUILTIN;
const byte PEDALPREV_LED = LED_BUILTIN;
const byte STATUS_LED = LED_BUILTIN;

const char thingName[] = "PushPush AIR";
const char wifiInitialApPassword[] = "12345678";

#define STRING_LEN 128

#define CONFIG_VERSION "beta2"

#define RESET_PASSWORD_PIN PEDALPREV_PIN

// -- Status indicator pin.
// #define STATUS_PIN LED_BUILTIN

void handleRoot();
void configSaved();
bool formValidator(iotwebconf::WebRequestWrapper* webRequestWrapper);

DNSServer dnsServer;
WebServer server(80);

char chooserPedNextKeyValue[STRING_LEN];
char chooserPedPrevKeyValue[STRING_LEN];

static char chooserValues[][STRING_LEN] = { "0xDA", "0xD9", "0xD8", "0xD7" };
static char chooserNames[][STRING_LEN] = { "KEY_UP_ARROW", "KEY_DOWN_ARROW", "KEY_LEFT_ARROW", "KEY_RIGHT_ARROW" };

IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION);

IotWebConfParameterGroup group1 = IotWebConfParameterGroup("group1", "Keystroke emulation");
IotWebConfSelectParameter chooserPedNextKey = IotWebConfSelectParameter("Choose", "chooserPedNextKey", chooserPedNextKeyValue, STRING_LEN, (char*)chooserValues, (char*)chooserNames, sizeof(chooserValues) / STRING_LEN, STRING_LEN);
IotWebConfSelectParameter chooserPedPrevKey = IotWebConfSelectParameter("Choose", "chooserPedPrevKey", chooserPedPrevKeyValue, STRING_LEN, (char*)chooserValues, (char*)chooserNames, sizeof(chooserValues) / STRING_LEN, STRING_LEN);

[...]
unrelated code removed
[...]

void setup(void)
{
    Serial.println("Starting up webconf...");
  group1.addItem(&chooserPedNextKey);
  group1.addItem(&chooserPedPrevKey);

  // iotWebConf.setStatusPin(STATUS_PIN);
  iotWebConf.setConfigPin(RESET_PASSWORD_PIN);
  iotWebConf.addParameterGroup(&group1);
  iotWebConf.setConfigSavedCallback(&configSaved);
  // iotWebConf.setFormValidator(&formValidator);
  // iotWebConf.getApTimeoutParameter()->visible = true;

  iotWebConf.disableBlink(); 
  iotWebConf.forceApMode(true);

    // -- Initializing the configuration.
    iotWebConf.init();

    // -- Set up required URL handlers on the web server.
    server.on("/", handleRoot);
    server.on("/config", []{ iotWebConf.handleConfig(); });
    server.onNotFound([](){ iotWebConf.handleNotFound(); });

    Serial.println("Done WebConf. Ready.");

   [...]
   unrelated code removed
   [...]
}
void loop(void)
{
   [...]
   unrelated code removed
  Here I read the button pressed and sent the keystroke via BLE... it's ok, tested on tens of gigs
   [...]

  iotWebConf.doLoop();
}

/**
 * Handle web requests to "/" path.
 */
void handleRoot()
{
  // -- Let IotWebConf test and handle captive portal requests.
  if (iotWebConf.handleCaptivePortal())
  {
    // -- Captive portal request were already served.
    return;
  }
  String s = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>";
  s += "<title>IotWebConf 03 Custom Parameters</title></head><body>Hello world!";
  s += "<ul>";
  s += "<li>Pedal Next Page: ";
  s += chooserPedNextKeyValue;
  s += "<li>Pedal Prev Page: ";
  s += chooserPedPrevKeyValue;
  s += "</ul>";
  s += "Go to <a href='config'>configure page</a> to change values.";
  s += "</body></html>\n";

  server.send(200, "text/html", s);
}

void configSaved()
{
  Serial.println("Configuration was updated.");
}

bool formValidator(iotwebconf::WebRequestWrapper* webRequestWrapper)
{
  Serial.println("Validating form.");
  bool valid = true;

/*
  int l = webRequestWrapper->arg(stringParam.getId()).length();
  if (l < 3)
  {
    stringParam.errorMessage = "Please provide at least 3 characters for this test!";
    valid = false;
  }
*/
  return valid;
}
ClemensGruber commented 2 years ago

Looks like hard coded without any option to avoid this:

https://github.com/prampec/IotWebConf/blob/b89ac9f61b2022cc0c794a74751c5019b4679eef/src/IotWebConf.cpp#L367-L376

ClemensGruber commented 2 years ago

Would be interested in a general solution also, without forking the lib! A kind of parameter if wifi parameters are obligatory.