Using new SoftAP Http pages to configure other settings


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:

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?


@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?

1 Like

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.


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


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();

    if (strcmp(url,"/index")==0) {
        Serial.println("sending redirect");
        Header h("Location: /index.html\r\n");
        cb(cbArg, 0, 301, "text/plain", &h);
    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);


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

    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);

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

STARTUP(softap_set_application_page_handler(myPage, nullptr));

void setup() {

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

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]);
                if (dataPos == datalength)
                    //for (uint32_t ms = millis(); millis() - ms <= 100; Particle.process());
                    datalength = body->read(contentData, sizeof(contentData));
                        if(datalength == -1)
                            Serial.println("Datalength -1");
                        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");


Issue is documented here: