feat(wifi): Standalone-AP im Treiber und im Startpfad
This commit is contained in:
+26
-3
@@ -111,6 +111,19 @@ int nl_app_set_wifi_credentials(const char *ssid, const char *pass)
|
|||||||
return nl_app_save_settings();
|
return nl_app_save_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nl_app_clear_standalone(void)
|
||||||
|
{
|
||||||
|
bool was_set;
|
||||||
|
|
||||||
|
nl_app_lock();
|
||||||
|
was_set = s_settings.standalone != 0;
|
||||||
|
s_settings.standalone = 0;
|
||||||
|
nl_app_unlock();
|
||||||
|
if (!was_set)
|
||||||
|
return 0; /* nichts zu schreiben - der Flash-Satz steht schon richtig */
|
||||||
|
return nl_app_save_settings();
|
||||||
|
}
|
||||||
|
|
||||||
void nl_app_factory_reset(void)
|
void nl_app_factory_reset(void)
|
||||||
{
|
{
|
||||||
printf("factory reset\r\n");
|
printf("factory reset\r\n");
|
||||||
@@ -228,10 +241,20 @@ static void app_task(void *arg)
|
|||||||
boot = s_settings;
|
boot = s_settings;
|
||||||
nl_app_unlock();
|
nl_app_unlock();
|
||||||
nl_mdns_set_name(boot.name);
|
nl_mdns_set_name(boot.name);
|
||||||
if (boot.wifi_ssid[0])
|
if (boot.standalone)
|
||||||
nl_wifi_start(boot.wifi_ssid, boot.wifi_pass, NINLIGHT_AP_PASSWORD);
|
/* Kein Verbindungsversuch: die Lampe steht ausdruecklich allein. Die gespeicherten
|
||||||
|
* Zugangsdaten gehen trotzdem mit - der Standalone-Zweig der Zustandsmaschine
|
||||||
|
* verbindet nicht, aber sie zaehlen wieder, sobald der Modus ueber die API
|
||||||
|
* zurueckgenommen wird; ohne sie landete die Lampe dann im offenen
|
||||||
|
* Onboarding-AP, obwohl ihr WLAN bekannt ist. */
|
||||||
|
nl_wifi_start(boot.wifi_ssid, boot.wifi_pass,
|
||||||
|
boot.ap_pass[0] ? boot.ap_pass : NINLIGHT_AP_PASSWORD,
|
||||||
|
boot.ap_ssid, boot.ap_channel, true, boot.standalone_pulse != 0);
|
||||||
|
else if (boot.wifi_ssid[0])
|
||||||
|
nl_wifi_start(boot.wifi_ssid, boot.wifi_pass, NINLIGHT_AP_PASSWORD, "", 0, false, false);
|
||||||
else
|
else
|
||||||
nl_wifi_start(NINLIGHT_WIFI_SSID, NINLIGHT_WIFI_PASSWORD, NINLIGHT_AP_PASSWORD);
|
nl_wifi_start(NINLIGHT_WIFI_SSID, NINLIGHT_WIFI_PASSWORD, NINLIGHT_AP_PASSWORD,
|
||||||
|
"", 0, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
nl_http_server_start(nl_app_api_ctx());
|
nl_http_server_start(nl_app_api_ctx());
|
||||||
|
|||||||
+13
-2
@@ -19,8 +19,12 @@ typedef struct {
|
|||||||
* sure the network task is still alive, not just the light task. */
|
* sure the network task is still alive, not just the light task. */
|
||||||
extern volatile uint32_t nl_net_beat;
|
extern volatile uint32_t nl_net_beat;
|
||||||
|
|
||||||
/* Starts the network task. An empty ssid starts the onboarding AP. Strings are copied. */
|
/* Starts the network task. An empty ssid starts the onboarding AP. Strings are copied.
|
||||||
void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass);
|
* Ein leerer ap_ssid heisst "wie der Hostname", ap_channel 0 heisst Kanal 6. Mit
|
||||||
|
* standalone == true wird gar nicht erst verbunden: die Lampe oeffnet ihren eigenen,
|
||||||
|
* passwortgeschuetzten AP, pulse laesst sie dabei kurz als Lebenszeichen pulsen. */
|
||||||
|
void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass,
|
||||||
|
const char *ap_ssid, uint8_t ap_channel, bool standalone, bool pulse);
|
||||||
/* Switches the SDK's own auto-connect off and drops any connection it may already have brought
|
/* Switches the SDK's own auto-connect off and drops any connection it may already have brought
|
||||||
* up on its own. nl_wifi_start() does this too, but the boot recovery path runs before that and
|
* up on its own. nl_wifi_start() does this too, but the boot recovery path runs before that and
|
||||||
* must not have the SDK joining its stored AP in parallel (I3, final review). Safe to call any
|
* must not have the SDK joining its stored AP in parallel (I3, final review). Safe to call any
|
||||||
@@ -34,6 +38,13 @@ void nl_wifi_disable_sdk_auto_connect(void);
|
|||||||
bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms);
|
bool nl_wifi_join_blocking(const char *ssid, const char *pass, uint32_t timeout_ms);
|
||||||
/* Starts an onboarding test with new credentials (from the HTTP task). 0 = queued. */
|
/* Starts an onboarding test with new credentials (from the HTTP task). 0 = queued. */
|
||||||
int nl_wifi_request_onboard(const char *ssid, const char *pass);
|
int nl_wifi_request_onboard(const char *ssid, const char *pass);
|
||||||
|
/* Schaltet den Standalone-Modus zur Laufzeit ein oder aus (aus dem HTTP-Task). Die Werte
|
||||||
|
* werden kopiert und erst im Netz-Task wirksam, nachdem die Antwort raus ist; ein leeres
|
||||||
|
* ssid/pass bzw. channel == 0 bedeutet jeweils die Vorgabe. 0 = uebernommen, sonst 503. */
|
||||||
|
int nl_wifi_request_standalone(bool enabled, const char *ssid, const char *pass,
|
||||||
|
uint8_t channel, bool pulse);
|
||||||
|
/* True, solange die Lampe in ihrem eigenen Dauer-AP steht. */
|
||||||
|
bool nl_wifi_is_standalone(void);
|
||||||
/* True while the unconfigured onboarding AP is open (API without token). */
|
/* True while the unconfigured onboarding AP is open (API without token). */
|
||||||
bool nl_wifi_open_access(void);
|
bool nl_wifi_open_access(void);
|
||||||
void nl_wifi_status(nl_wifi_status_t *out);
|
void nl_wifi_status(nl_wifi_status_t *out);
|
||||||
|
|||||||
+138
-13
@@ -18,6 +18,10 @@
|
|||||||
#define NL_NET_QUEUE 8
|
#define NL_NET_QUEUE 8
|
||||||
#define MSG_NETIF 0x100u /* | netif status */
|
#define MSG_NETIF 0x100u /* | netif status */
|
||||||
#define MSG_ONBOARD 0x200u
|
#define MSG_ONBOARD 0x200u
|
||||||
|
/* 0x400, nicht 0x300: die netif-Meldungen werden weiter unten mit (m & MSG_NETIF) erkannt,
|
||||||
|
* und 0x300 traegt das 0x100-Bit mit - die Standalone-Meldung waere als netif-Ereignis
|
||||||
|
* protokolliert worden. */
|
||||||
|
#define MSG_STANDALONE 0x400u
|
||||||
|
|
||||||
static u32 s_stack[768];
|
static u32 s_stack[768];
|
||||||
static tls_os_queue_t *s_queue;
|
static tls_os_queue_t *s_queue;
|
||||||
@@ -29,6 +33,18 @@ static char s_hostname[24];
|
|||||||
static char s_ssid[NL_SSID_LEN], s_pass[NL_PASS_LEN];
|
static char s_ssid[NL_SSID_LEN], s_pass[NL_PASS_LEN];
|
||||||
static char s_test_ssid[NL_SSID_LEN], s_test_pass[NL_PASS_LEN];
|
static char s_test_ssid[NL_SSID_LEN], s_test_pass[NL_PASS_LEN];
|
||||||
static char s_ap_pass[NL_PASS_LEN];
|
static char s_ap_pass[NL_PASS_LEN];
|
||||||
|
static char s_ap_ssid[NL_SSID_LEN]; /* leer = Hostname */
|
||||||
|
static uint8_t s_ap_channel = 6;
|
||||||
|
/* Die Daten, mit denen der laufende AP tatsaechlich aufgebaut wurde. Nur so ist zu sehen,
|
||||||
|
* ob ein Wunsch aus der API den AP wirklich veraendert - die Zustandsmaschine liefert kein
|
||||||
|
* start_ap, wenn der AP schon steht, und die alten Daten blieben sonst still in Kraft. */
|
||||||
|
static char s_ap_live_ssid[NL_SSID_LEN], s_ap_live_pass[NL_PASS_LEN];
|
||||||
|
static uint8_t s_ap_live_channel;
|
||||||
|
static bool s_ap_live;
|
||||||
|
/* 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 uint8_t s_req_ap_channel;
|
||||||
|
static bool s_req_enabled, s_req_pulse, s_req_pending;
|
||||||
static bool s_ap_create_pending; /* M3: tls_wifi_softap_create() failed, retry it */
|
static bool s_ap_create_pending; /* M3: tls_wifi_softap_create() failed, retry it */
|
||||||
static uint32_t s_ap_create_retry_at;
|
static uint32_t s_ap_create_retry_at;
|
||||||
|
|
||||||
@@ -88,18 +104,43 @@ void nl_wifi_disable_sdk_auto_connect(void)
|
|||||||
tls_wifi_disconnect();
|
tls_wifi_disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
static void destroy_ap(void)
|
||||||
|
{
|
||||||
|
tls_wifi_softap_destroy();
|
||||||
|
s_ap_create_pending = false;
|
||||||
|
s_ap_live = false;
|
||||||
|
clear_softap_param(); /* C2: every softap teardown clears the persisted SOFTAP bit */
|
||||||
|
}
|
||||||
|
|
||||||
static void start_ap(void)
|
static void start_ap(void)
|
||||||
{
|
{
|
||||||
struct tls_softap_info_t ap;
|
struct tls_softap_info_t ap;
|
||||||
struct tls_ip_info_t ip;
|
struct tls_ip_info_t ip;
|
||||||
|
const char *ssid = s_ap_ssid[0] ? s_ap_ssid : s_hostname;
|
||||||
size_t n = strlen(s_ap_pass);
|
size_t n = strlen(s_ap_pass);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
/* Steht derselbe AP schon, bleibt er stehen: die Zustandsmaschine verlangt start_ap
|
||||||
|
* auch dann, wenn sie den AP gar nicht erst abgebaut hat (fehlgeschlagener
|
||||||
|
* Onboarding-Versuch aus dem Standalone-Modus), und ein Neuaufbau wuerfe dort alle
|
||||||
|
* Clients ohne Not heraus. */
|
||||||
|
if (s_ap_live && strcmp(s_ap_live_ssid, ssid) == 0 && strcmp(s_ap_live_pass, s_ap_pass) == 0 &&
|
||||||
|
s_ap_live_channel == s_ap_channel)
|
||||||
|
return;
|
||||||
|
/* Umgekehrt: Name, Passwort oder Kanal haben sich geaendert, waehrend der AP steht.
|
||||||
|
* Ohne eigenen Abriss liefe er mit den alten Daten weiter. */
|
||||||
|
if (s_ap_live) {
|
||||||
|
printf("wifi: AP data changed, rebuilding\r\n");
|
||||||
|
destroy_ap();
|
||||||
|
}
|
||||||
|
|
||||||
memset(&ap, 0, sizeof ap);
|
memset(&ap, 0, sizeof ap);
|
||||||
memset(&ip, 0, sizeof ip);
|
memset(&ip, 0, sizeof ip);
|
||||||
copy((char *)ap.ssid, s_hostname, sizeof ap.ssid);
|
copy((char *)ap.ssid, ssid, sizeof ap.ssid);
|
||||||
ap.encrypt = IEEE80211_ENCRYT_CCMP_WPA2;
|
ap.encrypt = IEEE80211_ENCRYT_CCMP_WPA2;
|
||||||
ap.channel = 6;
|
ap.channel = s_ap_channel;
|
||||||
ap.keyinfo.format = 1; /* ascii */
|
ap.keyinfo.format = 1; /* ascii */
|
||||||
ap.keyinfo.index = 1;
|
ap.keyinfo.index = 1;
|
||||||
ap.keyinfo.key_len = (u8)n;
|
ap.keyinfo.key_len = (u8)n;
|
||||||
@@ -108,10 +149,17 @@ static void start_ap(void)
|
|||||||
ip.netmask[0] = 255; ip.netmask[1] = 255; ip.netmask[2] = 255; ip.netmask[3] = 0;
|
ip.netmask[0] = 255; ip.netmask[1] = 255; ip.netmask[2] = 255; ip.netmask[3] = 0;
|
||||||
memcpy(ip.dnsname, "local", 6);
|
memcpy(ip.dnsname, "local", 6);
|
||||||
r = tls_wifi_softap_create(&ap, &ip);
|
r = tls_wifi_softap_create(&ap, &ip);
|
||||||
printf("wifi: AP %s %s\r\n", s_hostname, r == WM_SUCCESS ? "up" : "failed");
|
printf("wifi: AP %s (ch %u) %s\r\n", ssid, (unsigned)s_ap_channel,
|
||||||
|
r == WM_SUCCESS ? "up" : "failed");
|
||||||
/* M3: retry a failed AP create instead of leaving onboarding/fallback without an AP. */
|
/* M3: retry a failed AP create instead of leaving onboarding/fallback without an AP. */
|
||||||
s_ap_create_pending = r != WM_SUCCESS;
|
s_ap_create_pending = r != WM_SUCCESS;
|
||||||
s_ap_create_retry_at = nl_app_now_ms() + 5000u;
|
s_ap_create_retry_at = nl_app_now_ms() + 5000u;
|
||||||
|
s_ap_live = r == WM_SUCCESS;
|
||||||
|
if (s_ap_live) {
|
||||||
|
copy(s_ap_live_ssid, ssid, sizeof s_ap_live_ssid);
|
||||||
|
copy(s_ap_live_pass, s_ap_pass, sizeof s_ap_live_pass);
|
||||||
|
s_ap_live_channel = s_ap_channel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void connect_station(bool test)
|
static void connect_station(bool test)
|
||||||
@@ -149,6 +197,12 @@ static void execute(nl_wifi_actions_t a)
|
|||||||
printf("wifi: onboarding ok, saving credentials for %s\r\n", ssid);
|
printf("wifi: onboarding ok, saving credentials for %s\r\n", ssid);
|
||||||
nl_app_set_wifi_credentials(ssid, pass);
|
nl_app_set_wifi_credentials(ssid, pass);
|
||||||
}
|
}
|
||||||
|
if (a.clear_standalone) {
|
||||||
|
/* Sonst stuende die Lampe nach dem naechsten Neustart wieder in ihrem eigenen AP,
|
||||||
|
* obwohl sie gerade erfolgreich ins WLAN gewechselt ist. */
|
||||||
|
printf("wifi: standalone mode cleared\r\n");
|
||||||
|
nl_app_clear_standalone();
|
||||||
|
}
|
||||||
if (a.pulse_on)
|
if (a.pulse_on)
|
||||||
pulse(true);
|
pulse(true);
|
||||||
if (a.pulse_off)
|
if (a.pulse_off)
|
||||||
@@ -157,9 +211,7 @@ static void execute(nl_wifi_actions_t a)
|
|||||||
start_ap();
|
start_ap();
|
||||||
if (a.stop_ap) {
|
if (a.stop_ap) {
|
||||||
printf("wifi: AP down\r\n");
|
printf("wifi: AP down\r\n");
|
||||||
tls_wifi_softap_destroy();
|
destroy_ap();
|
||||||
s_ap_create_pending = false;
|
|
||||||
clear_softap_param(); /* C2: every softap teardown clears the persisted SOFTAP bit */
|
|
||||||
}
|
}
|
||||||
if (a.disconnect) {
|
if (a.disconnect) {
|
||||||
printf("wifi: dropping stray/failed station attempt\r\n");
|
printf("wifi: dropping stray/failed station attempt\r\n");
|
||||||
@@ -186,6 +238,7 @@ static void net_task(void *arg)
|
|||||||
nl_wifi_actions_t ev, tick;
|
nl_wifi_actions_t ev, tick;
|
||||||
uint32_t m = 0, now;
|
uint32_t m = 0, now;
|
||||||
bool got_ip_event = false, connected_now, ap_wanted, unexpected_softap;
|
bool got_ip_event = false, connected_now, ap_wanted, unexpected_softap;
|
||||||
|
bool recheck_ap = false;
|
||||||
|
|
||||||
memset(&ev, 0, sizeof ev);
|
memset(&ev, 0, sizeof ev);
|
||||||
if (tls_os_queue_receive(s_queue, &msg, 0, HZ / 10) == TLS_OS_SUCCESS)
|
if (tls_os_queue_receive(s_queue, &msg, 0, HZ / 10) == TLS_OS_SUCCESS)
|
||||||
@@ -202,6 +255,28 @@ static void net_task(void *arg)
|
|||||||
ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, now);
|
ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_DISCONNECTED, NL_WIFI_ERR_NONE, now);
|
||||||
} else if (m == MSG_ONBOARD) {
|
} else if (m == MSG_ONBOARD) {
|
||||||
ev = nl_wifi_sm_onboard(&s_sm, now);
|
ev = nl_wifi_sm_onboard(&s_sm, now);
|
||||||
|
} else if (m == MSG_STANDALONE) {
|
||||||
|
/* Die Wunschwerte erst hier uebernehmen: der HTTP-Task hat sie abgelegt, der
|
||||||
|
* Netz-Task ist der einzige, der s_ap_* schreibt und start_ap() aufruft. */
|
||||||
|
if (s_req_enabled) {
|
||||||
|
copy(s_ap_ssid, s_req_ap_ssid, sizeof s_ap_ssid);
|
||||||
|
copy(s_ap_pass, s_req_ap_pass[0] ? s_req_ap_pass : NINLIGHT_AP_PASSWORD,
|
||||||
|
sizeof s_ap_pass);
|
||||||
|
s_ap_channel = s_req_ap_channel ? s_req_ap_channel : 6;
|
||||||
|
ev = nl_wifi_sm_standalone(&s_sm, s_req_pulse, now);
|
||||||
|
/* Steht der AP schon, liefert die Zustandsmaschine kein start_ap. Ob die
|
||||||
|
* neuen Daten einen Neuaufbau verlangen, entscheidet start_ap() selbst. */
|
||||||
|
recheck_ap = true;
|
||||||
|
} else {
|
||||||
|
/* Zurueck auf die Vorgaben: ein spaeterer Rueckfall- oder Onboarding-AP ist
|
||||||
|
* wieder der gewohnte "ninlight-<mac4>" mit dem einkompilierten Passwort,
|
||||||
|
* genau wie bei einer Lampe, die nie standalone war. */
|
||||||
|
s_ap_ssid[0] = '\0';
|
||||||
|
copy(s_ap_pass, NINLIGHT_AP_PASSWORD, sizeof s_ap_pass);
|
||||||
|
s_ap_channel = 6;
|
||||||
|
ev = nl_wifi_sm_leave_standalone(&s_sm, s_ssid[0] != '\0', now);
|
||||||
|
}
|
||||||
|
s_req_pending = false;
|
||||||
}
|
}
|
||||||
tick = nl_wifi_sm_tick(&s_sm, now);
|
tick = nl_wifi_sm_tick(&s_sm, now);
|
||||||
/* I1: a late/stray IP-up must not announce mDNS unless the SM actually settled on STA_CONNECTED. */
|
/* I1: a late/stray IP-up must not announce mDNS unless the SM actually settled on STA_CONNECTED. */
|
||||||
@@ -217,13 +292,16 @@ static void net_task(void *arg)
|
|||||||
|
|
||||||
if (unexpected_softap) {
|
if (unexpected_softap) {
|
||||||
printf("wifi: unexpected SDK softap while AP should be down, destroying it\r\n");
|
printf("wifi: unexpected SDK softap while AP should be down, destroying it\r\n");
|
||||||
tls_wifi_softap_destroy();
|
destroy_ap();
|
||||||
clear_softap_param();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m & MSG_NETIF)
|
if (m & MSG_NETIF)
|
||||||
printf("wifi: netif event %u\r\n", (unsigned)(m & 0xFFu));
|
printf("wifi: netif event %u\r\n", (unsigned)(m & 0xFFu));
|
||||||
execute(ev);
|
execute(ev);
|
||||||
|
/* Nach einem Wechsel in den Standalone-Modus: start_ap() baut den AP neu auf, wenn
|
||||||
|
* Name, Passwort oder Kanal sich geaendert haben, und tut sonst nichts. */
|
||||||
|
if (recheck_ap && ap_wanted)
|
||||||
|
start_ap();
|
||||||
execute(tick);
|
execute(tick);
|
||||||
if (got_ip_event && connected_now)
|
if (got_ip_event && connected_now)
|
||||||
nl_mdns_on_ip_up();
|
nl_mdns_on_ip_up();
|
||||||
@@ -237,7 +315,8 @@ static void net_task(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass)
|
void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass,
|
||||||
|
const char *ap_ssid, uint8_t ap_channel, bool standalone, bool pulse)
|
||||||
{
|
{
|
||||||
nl_wifi_actions_t a;
|
nl_wifi_actions_t a;
|
||||||
struct netif *nif;
|
struct netif *nif;
|
||||||
@@ -249,6 +328,8 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass)
|
|||||||
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);
|
copy(s_ap_pass, ap_pass, sizeof s_ap_pass);
|
||||||
|
copy(s_ap_ssid, ap_ssid, sizeof s_ap_ssid); /* leer = Hostname */
|
||||||
|
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. */
|
||||||
nl_wifi_disable_sdk_auto_connect();
|
nl_wifi_disable_sdk_auto_connect();
|
||||||
@@ -256,8 +337,7 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass)
|
|||||||
/* C2: the SDK already brought up its own softap (e.g. from NETIF_IP_NET_UP before
|
/* C2: the SDK already brought up its own softap (e.g. from NETIF_IP_NET_UP before
|
||||||
* we got a chance to run) - tear it down, our state machine owns AP lifecycle. */
|
* we got a chance to run) - tear it down, our state machine owns AP lifecycle. */
|
||||||
printf("wifi: destroying SDK-created softap left over from boot\r\n");
|
printf("wifi: destroying SDK-created softap left over from boot\r\n");
|
||||||
tls_wifi_softap_destroy();
|
destroy_ap();
|
||||||
clear_softap_param();
|
|
||||||
}
|
}
|
||||||
nif = tls_get_netif();
|
nif = tls_get_netif();
|
||||||
if (nif)
|
if (nif)
|
||||||
@@ -268,10 +348,11 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass)
|
|||||||
tls_netif_add_status_event(netif_event);
|
tls_netif_add_status_event(netif_event);
|
||||||
|
|
||||||
lock();
|
lock();
|
||||||
a = nl_wifi_sm_start(&s_sm, s_ssid[0] != '\0', false, false, nl_app_now_ms());
|
a = nl_wifi_sm_start(&s_sm, s_ssid[0] != '\0', standalone, pulse, nl_app_now_ms());
|
||||||
unlock();
|
unlock();
|
||||||
s_started = true;
|
s_started = true;
|
||||||
printf("wifi: %s, hostname %s\r\n", s_ssid[0] ? "station" : "onboarding AP", s_hostname);
|
printf("wifi: %s, hostname %s\r\n",
|
||||||
|
standalone ? "standalone AP" : (s_ssid[0] ? "station" : "onboarding AP"), s_hostname);
|
||||||
execute(a);
|
execute(a);
|
||||||
tls_os_task_create(NULL, "nl_net", net_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_NET_PRIO, 0);
|
tls_os_task_create(NULL, "nl_net", net_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_NET_PRIO, 0);
|
||||||
}
|
}
|
||||||
@@ -294,6 +375,50 @@ int nl_wifi_request_onboard(const char *ssid, const char *pass)
|
|||||||
return tls_os_queue_send(s_queue, (void *)MSG_ONBOARD, 0) == TLS_OS_SUCCESS ? 0 : -1;
|
return tls_os_queue_send(s_queue, (void *)MSG_ONBOARD, 0) == TLS_OS_SUCCESS ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nl_wifi_request_standalone(bool enabled, const char *ssid, const char *pass,
|
||||||
|
uint8_t channel, bool pulse)
|
||||||
|
{
|
||||||
|
bool busy;
|
||||||
|
|
||||||
|
if (!s_started)
|
||||||
|
return -1;
|
||||||
|
lock();
|
||||||
|
/* Wie beim Onboarding: nicht auf einen laufenden Test draufsatteln, und keinen zweiten
|
||||||
|
* Wunsch annehmen, solange der erste noch in der Warteschlange steht - er ueberschriebe
|
||||||
|
* dessen Werte, die Antwort haette aber schon 202 gesagt. */
|
||||||
|
busy = s_sm.state == NL_WIFI_ST_ONBOARD_TEST || s_req_pending;
|
||||||
|
if (!busy) {
|
||||||
|
copy(s_req_ap_ssid, ssid ? ssid : "", sizeof s_req_ap_ssid);
|
||||||
|
copy(s_req_ap_pass, pass ? pass : "", sizeof s_req_ap_pass);
|
||||||
|
s_req_ap_channel = channel;
|
||||||
|
s_req_enabled = enabled;
|
||||||
|
s_req_pulse = pulse;
|
||||||
|
s_req_pending = true;
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
if (busy)
|
||||||
|
return -1;
|
||||||
|
if (tls_os_queue_send(s_queue, (void *)MSG_STANDALONE, 0) != TLS_OS_SUCCESS) {
|
||||||
|
lock();
|
||||||
|
s_req_pending = false;
|
||||||
|
unlock();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nl_wifi_is_standalone(void)
|
||||||
|
{
|
||||||
|
bool r;
|
||||||
|
|
||||||
|
if (!s_started)
|
||||||
|
return false;
|
||||||
|
lock();
|
||||||
|
r = s_sm.state == NL_WIFI_ST_STANDALONE;
|
||||||
|
unlock();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
bool nl_wifi_open_access(void)
|
bool nl_wifi_open_access(void)
|
||||||
{
|
{
|
||||||
bool r;
|
bool r;
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ void nl_app_request_factory_reset(void);
|
|||||||
/* Stores new station credentials (from a successful onboarding test) and persists them. */
|
/* Stores new station credentials (from a successful onboarding test) and persists them. */
|
||||||
int nl_app_set_wifi_credentials(const char *ssid, const char *pass);
|
int nl_app_set_wifi_credentials(const char *ssid, const char *pass);
|
||||||
|
|
||||||
|
/* Loescht den Standalone-Modus dauerhaft (gelungenes Onboarding aus dem eigenen AP heraus).
|
||||||
|
* Name, Passwort und Kanal des AP bleiben stehen - sie zaehlen wieder, sobald der Modus
|
||||||
|
* erneut eingeschaltet wird. */
|
||||||
|
int nl_app_clear_standalone(void);
|
||||||
|
|
||||||
/* Clears the power-cycle counter ahead of the regular 5 s deadline (spec 5.5), idempotent.
|
/* Clears the power-cycle counter ahead of the regular 5 s deadline (spec 5.5), idempotent.
|
||||||
* Used by the boot recovery path once it knows this boot is a recovery boot: a successful
|
* Used by the boot recovery path once it knows this boot is a recovery boot: a successful
|
||||||
* recovery never returns to the app task, so without this the counter would keep growing
|
* recovery never returns to the app task, so without this the counter would keep growing
|
||||||
|
|||||||
@@ -80,6 +80,14 @@ static int save_settings(const nl_settings_t *s)
|
|||||||
static int wifi_configure(const char *ssid, const char *pass) { return nl_wifi_request_onboard(ssid, pass); }
|
static int wifi_configure(const char *ssid, const char *pass) { return nl_wifi_request_onboard(ssid, pass); }
|
||||||
static bool open_access(void) { return nl_wifi_open_access(); }
|
static bool open_access(void) { return nl_wifi_open_access(); }
|
||||||
|
|
||||||
|
/* Der Treiber nimmt den Wunsch nur entgegen; wirksam wird er im Netz-Task, nachdem die
|
||||||
|
* Antwort raus ist. 0 = uebernommen, sonst 503. */
|
||||||
|
static int standalone_configure(bool enabled, const char *ssid, const char *pass, uint8_t channel,
|
||||||
|
bool pulse)
|
||||||
|
{
|
||||||
|
return nl_wifi_request_standalone(enabled, ssid, pass, channel, pulse);
|
||||||
|
}
|
||||||
|
|
||||||
static void get_info(nl_sys_info_t *out)
|
static void get_info(nl_sys_info_t *out)
|
||||||
{
|
{
|
||||||
nl_wifi_status_t w;
|
nl_wifi_status_t w;
|
||||||
@@ -108,6 +116,7 @@ static void get_info(nl_sys_info_t *out)
|
|||||||
out->uptime_s = nl_app_now_ms() / 1000u;
|
out->uptime_s = nl_app_now_ms() / 1000u;
|
||||||
out->free_heap = tls_mem_get_avail_heapsize();
|
out->free_heap = tls_mem_get_avail_heapsize();
|
||||||
out->last_ota_error = nl_ota_last_error();
|
out->last_ota_error = nl_ota_last_error();
|
||||||
|
out->wifi_standalone = nl_wifi_is_standalone();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void factory_reset(void) { nl_app_request_factory_reset(); }
|
static void factory_reset(void) { nl_app_request_factory_reset(); }
|
||||||
@@ -131,12 +140,17 @@ const nl_api_ctx_t *nl_app_api_ctx(void)
|
|||||||
cJSON_InitHooks(&hooks);
|
cJSON_InitHooks(&hooks);
|
||||||
ctx.board = nl_board_get();
|
ctx.board = nl_board_get();
|
||||||
ctx.fw_version = NINLIGHT_FW_VERSION;
|
ctx.fw_version = NINLIGHT_FW_VERSION;
|
||||||
|
/* Zeigerziel ist ein statischer Puffer im Treiber und gilt ab nl_wifi_start(), das im
|
||||||
|
* Startpfad vor dem HTTP-Server laeuft. Ohne diese Zeile dereferenziert der
|
||||||
|
* Einstellungs-Handler NULL, wenn kein eigener AP-Name gesetzt ist. */
|
||||||
|
ctx.hostname = nl_wifi_hostname();
|
||||||
ctx.build_date = NINLIGHT_BUILD_DATE;
|
ctx.build_date = NINLIGHT_BUILD_DATE;
|
||||||
ctx.get_state = get_state;
|
ctx.get_state = get_state;
|
||||||
ctx.apply = apply;
|
ctx.apply = apply;
|
||||||
ctx.get_settings = get_settings;
|
ctx.get_settings = get_settings;
|
||||||
ctx.save_settings = save_settings;
|
ctx.save_settings = save_settings;
|
||||||
ctx.wifi_configure = wifi_configure;
|
ctx.wifi_configure = wifi_configure;
|
||||||
|
ctx.standalone_configure = standalone_configure;
|
||||||
ctx.open_access = open_access;
|
ctx.open_access = open_access;
|
||||||
ctx.get_info = get_info;
|
ctx.get_info = get_info;
|
||||||
ctx.factory_reset = factory_reset;
|
ctx.factory_reset = factory_reset;
|
||||||
|
|||||||
Reference in New Issue
Block a user