feat(api): Settings-Typ standalone und wifi.standalone in system/info
This commit is contained in:
@@ -259,6 +259,10 @@ static void handle_info(const nl_api_ctx_t *ctx, nl_api_response_t *resp)
|
||||
cJSON_AddStringToObject(w, "error", in.wifi_error);
|
||||
else
|
||||
cJSON_AddNullToObject(w, "error");
|
||||
/* "mode" allein reicht nicht: im Standalone-Betrieb ist es "ap", genau wie beim offenen
|
||||
* Onboarding-AP. Ohne dieses Feld boete die App einer fertig eingerichteten Lampe ein
|
||||
* Onboarding an. */
|
||||
cJSON_AddBoolToObject(w, "standalone", in.wifi_standalone);
|
||||
cJSON_AddNumberToObject(o, "uptime", in.uptime_s);
|
||||
cJSON_AddNumberToObject(o, "free_heap", in.free_heap);
|
||||
if (in.last_ota_error)
|
||||
@@ -314,6 +318,16 @@ static void handle_get_settings(const nl_api_ctx_t *ctx, nl_api_response_t *resp
|
||||
cJSON_AddStringToObject(sa, "layout", s.sacn_layout ? "rgb" : "dimmer");
|
||||
cJSON_AddNumberToObject(sa, "slots", nl_board_dmx_slots(ctx->board, s.sacn_layout != 0));
|
||||
}
|
||||
{
|
||||
cJSON *sa = cJSON_AddObjectToObject(o, "standalone");
|
||||
cJSON_AddBoolToObject(sa, "enabled", s.standalone != 0);
|
||||
/* Der WIRKSAME Name, nicht der gespeicherte: ohne eigenen Namen heisst der AP
|
||||
* wie der Hostname. Wer hier einen leeren String saehe, muesste die Vorgabe
|
||||
* selbst nachbilden. Das AP-Passwort steht bewusst nicht hier. */
|
||||
cJSON_AddStringToObject(sa, "ssid", s.ap_ssid[0] ? s.ap_ssid : (ctx->hostname ? ctx->hostname : ""));
|
||||
cJSON_AddNumberToObject(sa, "channel", s.ap_channel ? s.ap_channel : 6);
|
||||
cJSON_AddBoolToObject(sa, "pulse", s.standalone_pulse != 0);
|
||||
}
|
||||
reply_json(resp, 200, o);
|
||||
}
|
||||
|
||||
@@ -345,6 +359,58 @@ static void handle_put_settings(const nl_api_ctx_t *ctx, const nl_http_request_t
|
||||
cJSON_Delete(j);
|
||||
return;
|
||||
}
|
||||
} else if (strcmp(type, "standalone") == 0) {
|
||||
const cJSON *en = cJSON_GetObjectItemCaseSensitive(j, "enabled");
|
||||
const cJSON *pu = cJSON_GetObjectItemCaseSensitive(j, "pulse");
|
||||
const char *as = NULL, *ap = NULL;
|
||||
long ch = 0;
|
||||
int asp, app, chp;
|
||||
bool will_enable;
|
||||
|
||||
will_enable = cJSON_IsBool(en) && cJSON_IsTrue(en);
|
||||
asp = get_string(j, "ssid", 1, NL_SSID_LEN - 1, &as);
|
||||
app = get_string(j, "password", 8, NL_PASS_LEN - 1, &ap);
|
||||
chp = get_int(j, "channel", 1, 13, &ch);
|
||||
|
||||
if (!cJSON_IsBool(en)) {
|
||||
err = "invalid enabled";
|
||||
} else if (asp < 0) {
|
||||
err = "invalid ssid";
|
||||
} else if (app < 0) {
|
||||
/* Die Meldung nennt das Feld, nie den Wert: ein zu kurzes Passwort darf
|
||||
* nicht im Protokoll des Aufrufers landen. */
|
||||
err = "invalid password";
|
||||
} else if (chp < 0) {
|
||||
err = "invalid channel";
|
||||
} else if (will_enable && app != 1 && s.ap_pass[0] == '\0') {
|
||||
err = "password required";
|
||||
} else if (pu && !cJSON_IsBool(pu)) {
|
||||
err = "invalid pulse";
|
||||
} else {
|
||||
if (asp == 1)
|
||||
strcpy(s.ap_ssid, as);
|
||||
if (app == 1)
|
||||
strcpy(s.ap_pass, ap);
|
||||
if (chp == 1)
|
||||
s.ap_channel = (uint8_t)ch;
|
||||
if (pu)
|
||||
s.standalone_pulse = cJSON_IsTrue(pu) ? 1 : 0;
|
||||
s.standalone = will_enable ? 1 : 0;
|
||||
/* Wie bei "wifi" kehrt dieser Zweig hier zurueck statt ans gemeinsame Ende zu
|
||||
* laufen (das antwortet 200): der Wechsel zieht der Verbindung das Netz weg, die
|
||||
* Antwort ist 202 und muss vorher ausgefuellt sein. */
|
||||
if (ctx->save_settings(&s) != 0) {
|
||||
reply_error(resp, 500, "save failed");
|
||||
} else if (!ctx->standalone_configure ||
|
||||
ctx->standalone_configure(will_enable, s.ap_ssid, s.ap_pass,
|
||||
s.ap_channel, s.standalone_pulse != 0) != 0) {
|
||||
reply_error(resp, 503, "wifi busy");
|
||||
} else {
|
||||
reply(resp, 202, "{\"status\":\"standalone\"}");
|
||||
}
|
||||
cJSON_Delete(j);
|
||||
return;
|
||||
}
|
||||
} else if (strcmp(type, "device_name") == 0) {
|
||||
if (get_string(j, "name", 1, NL_NAME_LEN - 1, &a) != 1)
|
||||
err = "invalid name";
|
||||
|
||||
@@ -27,18 +27,24 @@ typedef struct {
|
||||
bool sacn_active; /* true, solange die Lampe ferngesteuert wird */
|
||||
bool sacn_joined; /* Multicast-Gruppe des Universe beigetreten */
|
||||
bool sacn_running; /* Empfangs-Task lebt und haelt einen Socket */
|
||||
bool wifi_standalone; /* eigener Dauer-AP, nicht der offene Onboarding-AP */
|
||||
} nl_sys_info_t;
|
||||
|
||||
/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */
|
||||
typedef struct {
|
||||
const nl_board_t *board;
|
||||
const char *fw_version;
|
||||
const char *hostname; /* "ninlight-<mac4>", Vorgabe fuer den AP-Namen */
|
||||
const char *build_date;
|
||||
void (*get_state)(nl_light_state_t *out);
|
||||
nl_ctrl_err_t (*apply)(const nl_light_change_t *c);
|
||||
void (*get_settings)(nl_settings_t *out);
|
||||
int (*save_settings)(const nl_settings_t *s); /* 0 = ok; wifi fields are ignored */
|
||||
int (*wifi_configure)(const char *ssid, const char *pass); /* 0 = onboarding test started */
|
||||
/* 0 = uebernommen (Antwort 202), sonst 503. Wie wifi_configure wirkt der Wechsel
|
||||
erst nach der Antwort - die Verbindung bricht sonst vor dem Senden weg. */
|
||||
int (*standalone_configure)(bool enabled, const char *ssid, const char *pass,
|
||||
uint8_t channel, bool pulse);
|
||||
bool (*open_access)(void); /* unconfigured onboarding AP */
|
||||
void (*get_info)(nl_sys_info_t *out);
|
||||
void (*factory_reset)(void); /* request only */
|
||||
|
||||
Reference in New Issue
Block a user