fix(wifi): AP-Daten nach dem Onboarding zuruecksetzen, Netz trotz abgelehntem AP-Aufbau
This commit is contained in:
+9
-1
@@ -10,6 +10,9 @@
|
|||||||
#define P_SETTINGS "/api/v1/system/settings"
|
#define P_SETTINGS "/api/v1/system/settings"
|
||||||
#define P_COMMAND "/api/v1/system/command"
|
#define P_COMMAND "/api/v1/system/command"
|
||||||
|
|
||||||
|
/* Obergrenze fuer das AP-Passwort des Standalone-Modus (WPA2-ASCII-Passphrase). */
|
||||||
|
#define NL_AP_PASS_MAX 63
|
||||||
|
|
||||||
static const char *const POB_NAMES[] = {"last", "on", "off"};
|
static const char *const POB_NAMES[] = {"last", "on", "off"};
|
||||||
|
|
||||||
static void reply(nl_api_response_t *r, int status, const char *json)
|
static void reply(nl_api_response_t *r, int status, const char *json)
|
||||||
@@ -370,7 +373,12 @@ static void handle_put_settings(const nl_api_ctx_t *ctx, const nl_http_request_t
|
|||||||
|
|
||||||
will_enable = cJSON_IsBool(en) && cJSON_IsTrue(en);
|
will_enable = cJSON_IsBool(en) && cJSON_IsTrue(en);
|
||||||
asp = get_string(j, "ssid", 1, NL_SSID_LEN - 1, &as);
|
asp = get_string(j, "ssid", 1, NL_SSID_LEN - 1, &as);
|
||||||
app = get_string(j, "password", 8, NL_PASS_LEN - 1, &ap);
|
/* 63, nicht NL_PASS_LEN - 1 (64): eine WPA2-ASCII-Passphrase darf hoechstens 63
|
||||||
|
* Zeichen haben. Bei 64 schriebe der Treiber keyinfo.key[64] randvoll ohne
|
||||||
|
* Abschlussbyte, und ob libwlan.a das annimmt, sieht man dem Binaerobjekt nicht an -
|
||||||
|
* ein abgelehnter AP-Aufbau ist hier aber eine ueber die API erreichbare Sackgasse.
|
||||||
|
* Der "wifi"-Zweig bleibt bewusst bei 64: dort haengt kein eigener AP daran. */
|
||||||
|
app = get_string(j, "password", 8, NL_AP_PASS_MAX, &ap);
|
||||||
chp = get_int(j, "channel", 1, 13, &ch);
|
chp = get_int(j, "channel", 1, 13, &ch);
|
||||||
|
|
||||||
if (!cJSON_IsBool(en)) {
|
if (!cJSON_IsBool(en)) {
|
||||||
|
|||||||
+51
-6
@@ -41,6 +41,12 @@ static uint8_t s_ap_channel = 6;
|
|||||||
static char s_ap_live_ssid[NL_SSID_LEN], s_ap_live_pass[NL_PASS_LEN];
|
static char s_ap_live_ssid[NL_SSID_LEN], s_ap_live_pass[NL_PASS_LEN];
|
||||||
static uint8_t s_ap_live_channel;
|
static uint8_t s_ap_live_channel;
|
||||||
static bool s_ap_live;
|
static bool s_ap_live;
|
||||||
|
/* Drei Versuche, dann der Rueckfall auf Daten, die schon einmal getragen haben: einer koennte
|
||||||
|
* ein Zufall sein (das Funkteil raeumt gerade den alten AP ab), aber drei hintereinander
|
||||||
|
* heissen, dass das Funkteil genau diese Daten nicht annimmt. Und 3 x 5 s hoechstens
|
||||||
|
* 15 s ohne AP ist kuerzer als jede Fehlersuche vor Ort. */
|
||||||
|
#define NL_AP_CREATE_TRIES 3
|
||||||
|
static uint8_t s_ap_create_fails;
|
||||||
/* Vom HTTP-Task gefuellt, vom Netz-Task uebernommen; beides unter s_lock. */
|
/* Vom HTTP-Task gefuellt, vom Netz-Task uebernommen; beides unter s_lock. */
|
||||||
static char s_req_ap_ssid[NL_SSID_LEN], s_req_ap_pass[NL_PASS_LEN];
|
static char s_req_ap_ssid[NL_SSID_LEN], s_req_ap_pass[NL_PASS_LEN];
|
||||||
static uint8_t s_req_ap_channel;
|
static uint8_t s_req_ap_channel;
|
||||||
@@ -104,6 +110,16 @@ void nl_wifi_disable_sdk_auto_connect(void)
|
|||||||
tls_wifi_disconnect();
|
tls_wifi_disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Setzt Name, Passwort und Kanal des naechsten AP auf die Vorgaben zurueck: "ninlight-<mac4>"
|
||||||
|
* mit dem einkompilierten Passwort auf Kanal 6. Beruehrt einen LAUFENDEN AP nicht - der
|
||||||
|
* behaelt seine Daten, bis er abgebaut und neu aufgebaut wird. */
|
||||||
|
static void reset_ap_defaults(void)
|
||||||
|
{
|
||||||
|
s_ap_ssid[0] = '\0';
|
||||||
|
copy(s_ap_pass, NINLIGHT_AP_PASSWORD, sizeof s_ap_pass);
|
||||||
|
s_ap_channel = 6;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reisst den AP ab und raeumt dabei auch die Buchfuehrung auf. Laeuft nur im Netz-Task
|
/* Reisst den AP ab und raeumt dabei auch die Buchfuehrung auf. Laeuft nur im Netz-Task
|
||||||
* (oder vor dessen Start) und nie unter s_lock - clear_softap_param() fasst SDK-Zustand an. */
|
* (oder vor dessen Start) und nie unter s_lock - clear_softap_param() fasst SDK-Zustand an. */
|
||||||
static void destroy_ap(void)
|
static void destroy_ap(void)
|
||||||
@@ -159,7 +175,28 @@ static void start_ap(void)
|
|||||||
copy(s_ap_live_ssid, ssid, sizeof s_ap_live_ssid);
|
copy(s_ap_live_ssid, ssid, sizeof s_ap_live_ssid);
|
||||||
copy(s_ap_live_pass, s_ap_pass, sizeof s_ap_live_pass);
|
copy(s_ap_live_pass, s_ap_pass, sizeof s_ap_live_pass);
|
||||||
s_ap_live_channel = s_ap_channel;
|
s_ap_live_channel = s_ap_channel;
|
||||||
|
s_ap_create_fails = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
/* Nimmt das Funkteil diese Daten dauerhaft nicht an, steht die Lampe ohne AP da - und mit
|
||||||
|
* in den Einstellungen gespeicherten Wunschdaten auch nach einem Neustart wieder. Dann
|
||||||
|
* lieber ein AP unter unerwartetem Namen: der ist sichtbar und reparierbar. */
|
||||||
|
if (++s_ap_create_fails < NL_AP_CREATE_TRIES)
|
||||||
|
return;
|
||||||
|
s_ap_create_fails = 0;
|
||||||
|
if (s_ap_live_ssid[0] && (strcmp(s_ap_live_ssid, ssid) != 0 ||
|
||||||
|
strcmp(s_ap_live_pass, s_ap_pass) != 0 ||
|
||||||
|
s_ap_live_channel != s_ap_channel)) {
|
||||||
|
printf("wifi: AP create keeps failing, falling back to the last working data (%s, ch %u)\r\n",
|
||||||
|
s_ap_live_ssid, (unsigned)s_ap_live_channel);
|
||||||
|
copy(s_ap_ssid, s_ap_live_ssid, sizeof s_ap_ssid);
|
||||||
|
copy(s_ap_pass, s_ap_live_pass, sizeof s_ap_pass);
|
||||||
|
s_ap_channel = s_ap_live_channel;
|
||||||
|
} else if (s_ap_ssid[0] || s_ap_channel != 6 || strcmp(s_ap_pass, NINLIGHT_AP_PASSWORD) != 0) {
|
||||||
|
printf("wifi: AP create keeps failing, falling back to %s on ch 6\r\n", s_hostname);
|
||||||
|
reset_ap_defaults();
|
||||||
|
}
|
||||||
|
/* Sonst scheitern schon die Vorgaben - dann bleibt nur, es weiter zu versuchen. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void connect_station(bool test)
|
static void connect_station(bool test)
|
||||||
@@ -201,6 +238,12 @@ static void execute(nl_wifi_actions_t a)
|
|||||||
/* Sonst stuende die Lampe nach dem naechsten Neustart wieder in ihrem eigenen AP,
|
/* Sonst stuende die Lampe nach dem naechsten Neustart wieder in ihrem eigenen AP,
|
||||||
* obwohl sie gerade erfolgreich ins WLAN gewechselt ist. */
|
* obwohl sie gerade erfolgreich ins WLAN gewechselt ist. */
|
||||||
printf("wifi: standalone mode cleared\r\n");
|
printf("wifi: standalone mode cleared\r\n");
|
||||||
|
/* Dieselbe Rueckstellung wie beim Zurueckschalten ueber die API: sonst kaeme ein
|
||||||
|
* spaeterer Rueckfall-AP (5 min ohne Station) mit Namen und Passwort des Nutzers
|
||||||
|
* hoch, obwohl standalone in den Einstellungen schon 0 ist. Gefahrlos, weil dieses
|
||||||
|
* Aktionsbuendel kein start_ap enthaelt - der noch laufende Standalone-AP bleibt
|
||||||
|
* unberuehrt, bis die Zustandsmaschine ihn abbaut. */
|
||||||
|
reset_ap_defaults();
|
||||||
nl_app_clear_standalone();
|
nl_app_clear_standalone();
|
||||||
}
|
}
|
||||||
if (a.pulse_on)
|
if (a.pulse_on)
|
||||||
@@ -270,10 +313,10 @@ static void net_task(void *arg)
|
|||||||
} else {
|
} else {
|
||||||
/* Zurueck auf die Vorgaben: ein spaeterer Rueckfall- oder Onboarding-AP ist
|
/* Zurueck auf die Vorgaben: ein spaeterer Rueckfall- oder Onboarding-AP ist
|
||||||
* wieder der gewohnte "ninlight-<mac4>" mit dem einkompilierten Passwort,
|
* wieder der gewohnte "ninlight-<mac4>" mit dem einkompilierten Passwort,
|
||||||
* genau wie bei einer Lampe, die nie standalone war. */
|
* genau wie bei einer Lampe, die nie standalone war. Das greift erst beim
|
||||||
s_ap_ssid[0] = '\0';
|
* NAECHSTEN Aufbau - der noch laufende AP behaelt Name und Passwort, bis ihn
|
||||||
copy(s_ap_pass, NINLIGHT_AP_PASSWORD, sizeof s_ap_pass);
|
* die Zustandsmaschine abbaut. */
|
||||||
s_ap_channel = 6;
|
reset_ap_defaults();
|
||||||
ev = nl_wifi_sm_leave_standalone(&s_sm, s_ssid[0] != '\0', now);
|
ev = nl_wifi_sm_leave_standalone(&s_sm, s_ssid[0] != '\0', now);
|
||||||
}
|
}
|
||||||
s_req_pending = false;
|
s_req_pending = false;
|
||||||
@@ -327,8 +370,10 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass,
|
|||||||
nl_names_hostname(s_mac, s_hostname, sizeof s_hostname);
|
nl_names_hostname(s_mac, s_hostname, sizeof s_hostname);
|
||||||
copy(s_ssid, ssid, sizeof s_ssid);
|
copy(s_ssid, ssid, sizeof s_ssid);
|
||||||
copy(s_pass, pass, sizeof s_pass);
|
copy(s_pass, pass, sizeof s_pass);
|
||||||
copy(s_ap_pass, ap_pass, sizeof s_ap_pass);
|
/* Wie in nl_wifi_request_standalone(): NULL ist hier zwar von keinem Aufrufer zu
|
||||||
copy(s_ap_ssid, ap_ssid, sizeof s_ap_ssid); /* leer = Hostname */
|
* erwarten, aber copy() wuerde darueber stolpern. */
|
||||||
|
copy(s_ap_pass, ap_pass && ap_pass[0] ? ap_pass : NINLIGHT_AP_PASSWORD, sizeof s_ap_pass);
|
||||||
|
copy(s_ap_ssid, ap_ssid ? ap_ssid : "", sizeof s_ap_ssid); /* leer = Hostname */
|
||||||
s_ap_channel = ap_channel ? ap_channel : 6;
|
s_ap_channel = ap_channel ? ap_channel : 6;
|
||||||
|
|
||||||
/* The SDK would otherwise reconnect on its own with credentials from its parameter area. */
|
/* The SDK would otherwise reconnect on its own with credentials from its parameter area. */
|
||||||
|
|||||||
+8
-1
@@ -728,11 +728,18 @@ static void test_standalone_length_limits(void)
|
|||||||
{
|
{
|
||||||
char body[256], pw[80], ss[48];
|
char body[256], pw[80], ss[48];
|
||||||
|
|
||||||
memset(pw, 'p', 64); pw[64] = '\0';
|
/* 63 ist die Obergrenze, nicht 64: eine WPA2-ASCII-Passphrase ist hoechstens 63 Zeichen
|
||||||
|
* lang, und ein vom Funkteil abgelehnter AP-Aufbau waere hier eine Sackgasse. */
|
||||||
|
memset(pw, 'p', 63); pw[63] = '\0';
|
||||||
snprintf(body, sizeof body, "{\"type\":\"standalone\",\"enabled\":true,\"password\":\"%s\"}", pw);
|
snprintf(body, sizeof body, "{\"type\":\"standalone\",\"enabled\":true,\"password\":\"%s\"}", pw);
|
||||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, body);
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, body);
|
||||||
TEST_ASSERT_EQUAL_INT(202, resp.status);
|
TEST_ASSERT_EQUAL_INT(202, resp.status);
|
||||||
TEST_ASSERT_EQUAL_STRING(pw, fake_standalone_pass);
|
TEST_ASSERT_EQUAL_STRING(pw, fake_standalone_pass);
|
||||||
|
memset(pw, 'p', 64); pw[64] = '\0';
|
||||||
|
snprintf(body, sizeof body, "{\"type\":\"standalone\",\"enabled\":true,\"password\":\"%s\"}", pw);
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, body);
|
||||||
|
TEST_ASSERT_EQUAL_INT(400, resp.status);
|
||||||
|
TEST_ASSERT_NULL(strstr(resp.body, pw));
|
||||||
memset(pw, 'p', 65); pw[65] = '\0';
|
memset(pw, 'p', 65); pw[65] = '\0';
|
||||||
snprintf(body, sizeof body, "{\"type\":\"standalone\",\"enabled\":true,\"password\":\"%s\"}", pw);
|
snprintf(body, sizeof body, "{\"type\":\"standalone\",\"enabled\":true,\"password\":\"%s\"}", pw);
|
||||||
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, body);
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, body);
|
||||||
|
|||||||
Reference in New Issue
Block a user