Using new SoftAP Http pages to configure other settings

Hi,

I was wondering how would it be possible to program other parameters with the SoftAP HTTP page on the particle photon.
I’m using currently the example of the documentation: https://docs.particle.io/reference/firmware/photon/#softap-http-pages

I would like to be able to configure my device this way because I might not have an internet access so I dont want to use the cloud functions. With a webpage like that, it would be possible to configure the photon with a phone, tablet and computer very easily.

I looked at the code and to send the password and ssid to the particle photon, the webpage call configure-ap.

Can anybody point me what should I look for to do that?
Is there a way to modifiy configure-ap to accept more parameters or create an other function like configure-ap or to do something directly inside the “myPage” Function?

Thanks!

@Suprazz, running SoftAP to provide a local configuration web page for user apps (not just wifi creds) is coming to v0.6.0 of the firmware with a nice API. :grinning:

I’m really happy to hear that!

What is the time frame for v0.6.0?

In the meantime, you can communicate between the webpage and the photon using HTTP requests, handled by the “myPage” function, so long as SYSTEM_THREAD(ENABLED) is called. Here’s my code to control the color of an Internet Button using a simple SoftAP webpage.

#pragma SPARK_NO_PREPROCESSOR

#include "Particle.h"
#include "softap_http.h"
#include "InternetButton.h"

SYSTEM_THREAD(ENABLED);

int r, g, b = 0;

struct Page
{
    const char* url;
    const char* mime_type;
    const char* data;
};


const char index_html[] = "<html><div align=\"center\"><form action=\"color\" method=\"get\"><input id=\"background-color\" name=\"color\" type=\"color\"/><input type=\"submit\" value=\"Go!\"/></form></div></html>";

Page myPages[] = {
     { "/index.html", "text/html", index_html },
     { nullptr }
};

void myPage(const char* url, ResponseCallback* cb, void* cbArg, Reader* body, Writer* result, void* reserved)
{
    String urlString = String(url);
    Serial.printlnf("handling page %s", url);
    char* data = body->fetch_as_string();
    Serial.println(String(data));
    free(data);

    if (strcmp(url,"/index")==0) {
        Serial.println("sending redirect");
        Header h("Location: /index.html\r\n");
        cb(cbArg, 0, 301, "text/plain", &h);
        return;
    }
    if (urlString.indexOf("/color") != -1) {
        r = (int)strtol(urlString.substring(14, 16).c_str(), nullptr, 16);
        g = (int)strtol(urlString.substring(16, 18).c_str(), nullptr, 16);
        b = (int)strtol(urlString.substring(18).c_str(), nullptr, 16);
        Serial.println(r);
        Serial.println(g);
        Serial.println(b);

    }

    int8_t idx = 0;
    for (;;idx++) {
        Page& p = myPages[idx];
        if (!p.url) {
            idx = -1;
            break;
        }
        else if (strcmp(url, p.url)==0) {
            break;
        }
    }

    if (idx==-1) {
        Header h("Location: /index.html\r\n");
        cb(cbArg, 0, 301, "text/plain", &h);
    }
    else {
        cb(cbArg, 0, 200, myPages[idx].mime_type, nullptr);
        result->write(myPages[idx].data);
    }
}

unsigned long t = 0;
InternetButton button = InternetButton();

STARTUP(softap_set_application_page_handler(myPage, nullptr));

void setup() {
    WiFi.listen();
    button.begin();
}

void loop() {
    if (millis()-t >= 200) {
        button.allLedsOn(r, g, b);
        t = millis();
    }
}

Thanks! So simple!

I have an issue if I try to load a lot of data.
I’m trying to send a firmware upgrade via a form to the device in softap mode.
I’m able to receive around half of data (11k over 27k) and after that the connection close and body->read return zero but body->bytes_left return 14863.

I did a wireshark and I can see that all the data is send correctly to the photon.

I’m doing this code in myPage function.

I’m not sure what else I can do because I’m in listening mode and the main loop is not executed
I tried to add delays and Particle.Process() without success…

btw I tried with 0.5.2 and 0.6.0 rc2

if (urlString.indexOf("/upgrade") != -1) {
//Serial.println(body->bytes_left, DEC);

// voici le output:
/*
POST Data: ------WebKitFormBoundaryEEbsS0VLVz50qOeT
Content-Disposition: form-data; name="myfile"; filename="binfile"
Content-Type: application/octet-stream

content file here...
*/

uint8_t contentData[512];
int dataPos;
int datalength = body->read(contentData, sizeof(contentData));
String contentString = String((const char*)contentData);
Serial.print((const char*)&contentData[0]);

dataPos = contentString.indexOf("filename=");
Serial.printlnf("Index of filename: %d", dataPos);

if(dataPos != -1)
{
    // Get filename here if we want
    String filename = contentString.substring(dataPos + 10, contentString.indexOf("Content-Type")-1);
    Serial.printlnf("Filename: %s", filename.c_str());
}


dataPos = contentString.indexOf("octet-stream");
Serial.printlnf("Index of octet-stream: %d", dataPos);
if(dataPos != -1)
{
    dataPos += 12 + 4;            
    Serial.println("Data start here:");
    datalength -= dataPos;

    while (body->bytes_left)
{
                // dump data on serial port for now
                Serial.printf("%.2x", contentData[dataPos]);
                dataPos++;
                if (dataPos == datalength)
                {
                    //for (uint32_t ms = millis(); millis() - ms <= 100; Particle.process());
                    datalength = body->read(contentData, sizeof(contentData));
                    do
                    {
                        if(datalength == -1)
                            Serial.println("Datalength -1");
                        delay(50);
                        datalength = body->read(contentData, sizeof(contentData));
                        if (datalength == 0)
                        {
                            Serial.printlnf("Length = 0, Bytes left: %d", body->bytes_left);
                        }
                    } while (datalength <= 0 && body->bytes_left);
                    dataPos = 0;
                }
            }
        Serial.println("No more data");
        delay(20);    
    }

Thanks!

Issue is documented here: https://github.com/spark/firmware/issues/1131