Web server for OTA configuration
Pronoe opened this issue · comments
Hello,
When the Web server has been activated once, it is never possible to activate it again for any modification, excepted by flashing again the device.
Then, on my local version of bootstrapper library, I have added a boolean parameter "forceWebServer" that force the OTA configuration when set.
I use this feature to activate OTA configuration when the device is switched ON/OFF twice quickly.
I use a json file to store power ON information that allows specific ON/OFF sequence detection.
If you feel this could be useful for a future version of your library, I can provide additional information on the code.
Also, it would be useful to add the gateway IP in the config.json file.
I was not able at the beginning to set a static IP address for the controller device because the gateway IP was not set correctly.
Regards.
Patrick
Hi Pronoe,
sure it could be useful..
Can you show me your code?
Thank you very much!
Hi Davide,
I have used a very basic method, surely not very elegant but it works.
Fisrt I have added at the end of BootstrapManager.h
the following variable declaration:
boolean forceWebServer; // if true, forces the use of launchWebServerForOTAConfig
Then in the void BootstrapManager::bootstrapSetup
code inside BootstarpManager.cpp
, I have changed
if (isWifiConfigured())
into if (isWifiConfigured() && !forceWebServer)
(line 33 in the original file).
My user code is for example the following:
const uint32_t shortPowerOn = 10; // threshold in s for identification of short power On
// Datastore management
// try to read a datastore file
if (readDS(true) != NO_ERROR)
{
// file does not exists or integrity error
// Then init datastore information
devicePowerUp = 1;
currentDeviceActivity = max(millis() / 1000, 1UL);
deviceActivity_1 = 0;
deviceActivity_2 = 0;
cumulativeDeviceActivity = millis() / 1000;
cumulativeDeviceActivityAtPowerOn = 0;
saveDS(); // save datastore (use readSPIFFS & data integrity checking with hash code)
}
else
{
// detection of double short power ON sequence
bootstrapManager.forceWebServer = ((deviceActivity_1 < shortPowerOn) && (deviceActivity_1 > 0) && (deviceActivity_2 < shortPowerOn) && (deviceActivity_2 > 0));
// note: deviceActivity_1 and deviceActivity_2 are the power ON duration of the 2 previous sequences
// update power on information
if (bootstrapManager.forceWebServer)
{
currentDeviceActivity = 120; // takes into account the webserver activity because as the ESP will be restarted, DS will not be updated - typical duration 120 s
}
else
{
currentDeviceActivity = max(millis() / 1000, 1UL); // takes into account current elapsed time
}
cumulativeDeviceActivityAtPowerOn = cumulativeDeviceActivity;
cumulativeDeviceActivity += currentDeviceActivity;
// save immediatly datastore for the case of a short power ON
saveDS(); // save datastore (use writeToSPIFFS)
}
// bootstrap manager setup
bootstrapManager.bootstrapSetup(manageDisconnections, manageHardwareButton, callback);
A better method would be to add an optional parameter forceWebServer
in the function bootstrapSetup
, with false
as default value.
Alternatively, you could add a function setWebServerOption
to configure the variable forceWebServer
or a function eraseSetupFile
that could be called before bootstrapSetup
.
For information, my code for saveDS and readDS
void saveDS()
// save current context in datastore file
{
DynamicJsonDocument DSdoc(1024);
DSdoc["header"] = "Header";
DSdoc["cumulativeDeviceActivity"] = String(cumulativeDeviceActivity);
DSdoc["lastDeviceActivity_1"] = String(currentDeviceActivity);
DSdoc["lastDeviceActivity_2"] = String(deviceActivity_1);
DSdoc["devicePowerUp"] = String(devicePowerUp);
DSdoc["lastEvent"] = lastPumpControlerEvent;
// computes and stores hash code for data integrity monitoring
DSdoc["HC"] = "null"; // hash code is calculated on the data including the CS, then this one must be set to a fix value before
String hashDS = hashPayload(DSdoc);// computes the hash code
DSdoc["HC"] = String(hashDS);
// save the file
bootstrapManager.writeToSPIFFS(DSdoc, "DS.json");
}```
```CPP
boolean readDS(boolean initValue)
// try to read datastore file and return true if successfull
{
enum fileErrorCode fileError = NO_ERROR;
// retrieve DS file informations
DynamicJsonDocument DSdoc = bootstrapManager.readSPIFFS("DS.json");
const char* header = DSdoc["header"];
if (header)
{
// file already exists and contains a header, then retrieve number of power up and cumulative up time
if (initValue)
{
// init global parameter when readDS at power ON
Serial.println("---- Init time parameters from DS file ----");
cumulativeDeviceActivity = helper.getValue(DSdoc["cumulativeDeviceActivity"]).toInt() + millis() / 1000;
deviceActivity_1 = helper.getValue(DSdoc["lastDeviceActivity_1"]).toInt();
deviceActivity_2 = helper.getValue(DSdoc["lastDeviceActivity_2"]).toInt();
devicePowerUp = 1 + helper.getValue(DSdoc["devicePowerUp"]).toInt();
lastSavedEvent = "Last saved event : " + helper.getValue(DSdoc["lastEvent"]);
}
// check data integrity
String readHashDS = helper.getValue(DSdoc["HC"]);
Serial.println("Read hash code: " + readHashDS);
DSdoc["HC"] = "null"; // hash code is calculated on the data including the CS, then this one must be set to a fix value before
String hashDS = hashPayload(DSdoc);// computes the hash code
if (hashDS == readHashDS)
{
Serial.println("file hash code OK");
}
else
{
lastPumpControlerEvent = "Integrity error in data store";
Serial.println(lastPumpControlerEvent);
fileError = INTEGRITY_ERROR;
}
}
else
{
// files does not exist or does not contain a header
fileError = OPENING_ERROR;
lastPumpControlerEvent = "DS file opening error";
Serial.println(lastPumpControlerEvent);
}
return fileError;
}
These are preliminary versions. Later on I will add information on pump running time and use duplicated DS file storage to prevent total loss of information in the case of power supply lost during file writing and then corruption of the file.
Thank you for the reply,
Arduino Bootstrapper is a generic lib and can't have the "logic on a pump" inside it but I'll get the idea to implement the possibility to change the wifi settings.
I have so many things to do, it will take some time but I'll do it. :)
Thank you.
Hi Davide,
Thank you for your reply.
Actually, I imagine that the connected things that can be developed with the help of your generic library, might be given later on to people having no software skill nor any software tools (my parents, my friends, the future buyer of my house, ...).
Then I think that these smart things should be reconfigurable easily through their interfaces if any (keyboard, touch screen) or through a web server as it is the case for example with smart lamps or weather stations.
This OTA function does exist in your library and this is very appreciable but it is activated only after the initial flashing.
Then I think that a mechanism that would allow to activate it on demand would be a good enhancement.
Of course, the code that would set this activation (with double short power ON, push buttons, ...) should be in the user application and not the library.
If you agree, I could commit a new version with this feature (something more elegant than my current local version).
I just need some training with the use of Github as I don't have yet much experience.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days
pending pull request