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);
|
cJSON_AddStringToObject(w, "error", in.wifi_error);
|
||||||
else
|
else
|
||||||
cJSON_AddNullToObject(w, "error");
|
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, "uptime", in.uptime_s);
|
||||||
cJSON_AddNumberToObject(o, "free_heap", in.free_heap);
|
cJSON_AddNumberToObject(o, "free_heap", in.free_heap);
|
||||||
if (in.last_ota_error)
|
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_AddStringToObject(sa, "layout", s.sacn_layout ? "rgb" : "dimmer");
|
||||||
cJSON_AddNumberToObject(sa, "slots", nl_board_dmx_slots(ctx->board, s.sacn_layout != 0));
|
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);
|
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);
|
cJSON_Delete(j);
|
||||||
return;
|
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) {
|
} else if (strcmp(type, "device_name") == 0) {
|
||||||
if (get_string(j, "name", 1, NL_NAME_LEN - 1, &a) != 1)
|
if (get_string(j, "name", 1, NL_NAME_LEN - 1, &a) != 1)
|
||||||
err = "invalid name";
|
err = "invalid name";
|
||||||
|
|||||||
@@ -27,18 +27,24 @@ typedef struct {
|
|||||||
bool sacn_active; /* true, solange die Lampe ferngesteuert wird */
|
bool sacn_active; /* true, solange die Lampe ferngesteuert wird */
|
||||||
bool sacn_joined; /* Multicast-Gruppe des Universe beigetreten */
|
bool sacn_joined; /* Multicast-Gruppe des Universe beigetreten */
|
||||||
bool sacn_running; /* Empfangs-Task lebt und haelt einen Socket */
|
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;
|
} nl_sys_info_t;
|
||||||
|
|
||||||
/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */
|
/* Everything the API needs from the application; implemented by src/sys/nl_app_api.c. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const nl_board_t *board;
|
const nl_board_t *board;
|
||||||
const char *fw_version;
|
const char *fw_version;
|
||||||
|
const char *hostname; /* "ninlight-<mac4>", Vorgabe fuer den AP-Namen */
|
||||||
const char *build_date;
|
const char *build_date;
|
||||||
void (*get_state)(nl_light_state_t *out);
|
void (*get_state)(nl_light_state_t *out);
|
||||||
nl_ctrl_err_t (*apply)(const nl_light_change_t *c);
|
nl_ctrl_err_t (*apply)(const nl_light_change_t *c);
|
||||||
void (*get_settings)(nl_settings_t *out);
|
void (*get_settings)(nl_settings_t *out);
|
||||||
int (*save_settings)(const nl_settings_t *s); /* 0 = ok; wifi fields are ignored */
|
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 */
|
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 */
|
bool (*open_access)(void); /* unconfigured onboarding AP */
|
||||||
void (*get_info)(nl_sys_info_t *out);
|
void (*get_info)(nl_sys_info_t *out);
|
||||||
void (*factory_reset)(void); /* request only */
|
void (*factory_reset)(void); /* request only */
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "fake_api_ctx.h"
|
#include "fake_api_ctx.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "light/nl_boot_state.h"
|
#include "light/nl_boot_state.h"
|
||||||
@@ -12,6 +13,10 @@ nl_ctrl_err_t fake_apply_result;
|
|||||||
int fake_apply_calls, fake_save_calls, fake_save_result;
|
int fake_apply_calls, fake_save_calls, fake_save_result;
|
||||||
int fake_wifi_calls, fake_wifi_result;
|
int fake_wifi_calls, fake_wifi_result;
|
||||||
char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN];
|
char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN];
|
||||||
|
int fake_standalone_calls, fake_standalone_result;
|
||||||
|
bool fake_standalone_enabled, fake_standalone_pulse;
|
||||||
|
char fake_standalone_ssid[NL_SSID_LEN], fake_standalone_pass[NL_PASS_LEN];
|
||||||
|
uint8_t fake_standalone_channel;
|
||||||
int fake_factory_calls, fake_ping_calls, fake_fw_result;
|
int fake_factory_calls, fake_ping_calls, fake_fw_result;
|
||||||
char fake_fw_url[256];
|
char fake_fw_url[256];
|
||||||
bool fake_open;
|
bool fake_open;
|
||||||
@@ -49,6 +54,18 @@ static int wifi_configure(const char *ssid, const char *pass)
|
|||||||
return fake_wifi_result;
|
return fake_wifi_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int fake_standalone_configure(bool enabled, const char *ssid, const char *pass,
|
||||||
|
uint8_t channel, bool pulse)
|
||||||
|
{
|
||||||
|
fake_standalone_calls++;
|
||||||
|
fake_standalone_enabled = enabled;
|
||||||
|
fake_standalone_pulse = pulse;
|
||||||
|
fake_standalone_channel = channel;
|
||||||
|
snprintf(fake_standalone_ssid, sizeof fake_standalone_ssid, "%s", ssid ? ssid : "");
|
||||||
|
snprintf(fake_standalone_pass, sizeof fake_standalone_pass, "%s", pass ? pass : "");
|
||||||
|
return fake_standalone_result;
|
||||||
|
}
|
||||||
|
|
||||||
static bool open_access(void) { return fake_open; }
|
static bool open_access(void) { return fake_open; }
|
||||||
static void get_info(nl_sys_info_t *out) { *out = fake_info; }
|
static void get_info(nl_sys_info_t *out) { *out = fake_info; }
|
||||||
static void factory_reset(void) { fake_factory_calls++; }
|
static void factory_reset(void) { fake_factory_calls++; }
|
||||||
@@ -83,6 +100,10 @@ void fake_api_reset(const char *board_id)
|
|||||||
fake_apply_calls = fake_save_calls = fake_save_result = 0;
|
fake_apply_calls = fake_save_calls = fake_save_result = 0;
|
||||||
fake_wifi_calls = fake_wifi_result = 0;
|
fake_wifi_calls = fake_wifi_result = 0;
|
||||||
fake_wifi_ssid[0] = fake_wifi_pass[0] = '\0';
|
fake_wifi_ssid[0] = fake_wifi_pass[0] = '\0';
|
||||||
|
fake_standalone_calls = fake_standalone_result = 0;
|
||||||
|
fake_standalone_enabled = fake_standalone_pulse = false;
|
||||||
|
fake_standalone_ssid[0] = fake_standalone_pass[0] = '\0';
|
||||||
|
fake_standalone_channel = 0;
|
||||||
fake_factory_calls = fake_ping_calls = 0;
|
fake_factory_calls = fake_ping_calls = 0;
|
||||||
fake_fw_result = -1;
|
fake_fw_result = -1;
|
||||||
fake_fw_url[0] = '\0';
|
fake_fw_url[0] = '\0';
|
||||||
@@ -96,6 +117,8 @@ void fake_api_reset(const char *board_id)
|
|||||||
fake_ctx.get_settings = get_settings;
|
fake_ctx.get_settings = get_settings;
|
||||||
fake_ctx.save_settings = save_settings;
|
fake_ctx.save_settings = save_settings;
|
||||||
fake_ctx.wifi_configure = wifi_configure;
|
fake_ctx.wifi_configure = wifi_configure;
|
||||||
|
fake_ctx.standalone_configure = fake_standalone_configure;
|
||||||
|
fake_ctx.hostname = "ninlight-681f";
|
||||||
fake_ctx.open_access = open_access;
|
fake_ctx.open_access = open_access;
|
||||||
fake_ctx.get_info = get_info;
|
fake_ctx.get_info = get_info;
|
||||||
fake_ctx.factory_reset = factory_reset;
|
fake_ctx.factory_reset = factory_reset;
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ extern nl_ctrl_err_t fake_apply_result;
|
|||||||
extern int fake_apply_calls, fake_save_calls, fake_save_result;
|
extern int fake_apply_calls, fake_save_calls, fake_save_result;
|
||||||
extern int fake_wifi_calls, fake_wifi_result;
|
extern int fake_wifi_calls, fake_wifi_result;
|
||||||
extern char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN];
|
extern char fake_wifi_ssid[NL_SSID_LEN], fake_wifi_pass[NL_PASS_LEN];
|
||||||
|
extern int fake_standalone_calls, fake_standalone_result;
|
||||||
|
extern bool fake_standalone_enabled, fake_standalone_pulse;
|
||||||
|
extern char fake_standalone_ssid[NL_SSID_LEN], fake_standalone_pass[NL_PASS_LEN];
|
||||||
|
extern uint8_t fake_standalone_channel;
|
||||||
extern int fake_factory_calls, fake_ping_calls, fake_fw_result;
|
extern int fake_factory_calls, fake_ping_calls, fake_fw_result;
|
||||||
extern char fake_fw_url[256];
|
extern char fake_fw_url[256];
|
||||||
extern bool fake_open;
|
extern bool fake_open;
|
||||||
|
|||||||
+174
@@ -589,6 +589,169 @@ static void test_put_sacn_layout_and_start_slot_together(void)
|
|||||||
TEST_ASSERT_EQUAL_UINT16(510, fake_settings.sacn_start_slot);
|
TEST_ASSERT_EQUAL_UINT16(510, fake_settings.sacn_start_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- standalone --- */
|
||||||
|
|
||||||
|
static void test_standalone_requires_a_password(void)
|
||||||
|
{
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":true}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(400, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("password required", error_text());
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_standalone_calls);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_save_calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ein gespeichertes Passwort genuegt - man soll den Kanal aendern koennen, ohne das
|
||||||
|
* Passwort erneut zu schicken. */
|
||||||
|
static void test_standalone_keeps_a_stored_password(void)
|
||||||
|
{
|
||||||
|
strcpy(fake_settings.ap_pass, "geheim123");
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN,
|
||||||
|
"{\"type\":\"standalone\",\"enabled\":true,\"channel\":11}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(202, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_INT(11, fake_standalone_channel);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("geheim123", fake_standalone_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_standalone_rejects_a_short_password(void)
|
||||||
|
{
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN,
|
||||||
|
"{\"type\":\"standalone\",\"enabled\":true,\"password\":\"1234567\"}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(400, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("invalid password", error_text());
|
||||||
|
/* Die Fehlermeldung nennt das Feld, nie den Wert. */
|
||||||
|
TEST_ASSERT_NULL(strstr(resp.body, "1234567"));
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_standalone_calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_standalone_rejects_a_channel_outside_the_band(void)
|
||||||
|
{
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN,
|
||||||
|
"{\"type\":\"standalone\",\"enabled\":true,\"password\":\"geheim123\",\"channel\":14}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(400, resp.status);
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN,
|
||||||
|
"{\"type\":\"standalone\",\"enabled\":true,\"password\":\"geheim123\",\"channel\":0}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(400, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_standalone_calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_standalone_accepts_a_full_request(void)
|
||||||
|
{
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN,
|
||||||
|
"{\"type\":\"standalone\",\"enabled\":true,\"password\":\"geheim123\","
|
||||||
|
"\"ssid\":\"Wohnzimmerlampe\",\"channel\":6,\"pulse\":false}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(202, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("standalone", cJSON_GetStringValue(field("status")));
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, fake_standalone_calls);
|
||||||
|
TEST_ASSERT_TRUE(fake_standalone_enabled);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("Wohnzimmerlampe", fake_standalone_ssid);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("geheim123", fake_standalone_pass);
|
||||||
|
TEST_ASSERT_EQUAL_INT(6, fake_standalone_channel);
|
||||||
|
TEST_ASSERT_FALSE(fake_standalone_pulse);
|
||||||
|
/* Gespeichert wird auch: sonst ist der Modus nach dem Neustart weg. */
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, fake_save_calls);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(1, fake_settings.standalone);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("geheim123", fake_settings.ap_pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Abschalten braucht kein Passwort. */
|
||||||
|
static void test_standalone_can_be_switched_off(void)
|
||||||
|
{
|
||||||
|
fake_settings.standalone = 1;
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":false}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(202, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, fake_standalone_calls);
|
||||||
|
TEST_ASSERT_FALSE(fake_standalone_enabled);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, fake_settings.standalone);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_standalone_reports_a_busy_radio_and_a_failed_save(void)
|
||||||
|
{
|
||||||
|
strcpy(fake_settings.ap_pass, "geheim123");
|
||||||
|
fake_standalone_result = -1;
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":true}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(503, resp.status);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("wifi busy", error_text());
|
||||||
|
|
||||||
|
fake_standalone_result = 0;
|
||||||
|
fake_standalone_calls = 0;
|
||||||
|
fake_save_result = -1;
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":true}");
|
||||||
|
TEST_ASSERT_EQUAL_INT(500, resp.status);
|
||||||
|
/* Ohne gespeicherten Datensatz darf der Wechsel nicht angestossen werden. */
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_standalone_calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_standalone_rejects_bad_types_of_the_other_fields(void)
|
||||||
|
{
|
||||||
|
strcpy(fake_settings.ap_pass, "geheim123");
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":\"yes\"}");
|
||||||
|
TEST_ASSERT_EQUAL_STRING("invalid enabled", error_text());
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":true,\"pulse\":1}");
|
||||||
|
TEST_ASSERT_EQUAL_STRING("invalid pulse", error_text());
|
||||||
|
call(NL_HTTP_PUT, "/api/v1/system/settings", TOKEN, "{\"type\":\"standalone\",\"enabled\":true,\"ssid\":\"\"}");
|
||||||
|
TEST_ASSERT_EQUAL_STRING("invalid ssid", error_text());
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, fake_standalone_calls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Das AP-Passwort darf nirgends in der Antwort auftauchen. */
|
||||||
|
static void test_settings_show_standalone_without_the_password(void)
|
||||||
|
{
|
||||||
|
cJSON *o, *sa;
|
||||||
|
fake_settings.standalone = 1;
|
||||||
|
fake_settings.ap_channel = 11;
|
||||||
|
fake_settings.standalone_pulse = 0;
|
||||||
|
strcpy(fake_settings.ap_ssid, "Wohnzimmerlampe");
|
||||||
|
strcpy(fake_settings.ap_pass, "geheim123");
|
||||||
|
call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL);
|
||||||
|
TEST_ASSERT_EQUAL_INT(200, resp.status);
|
||||||
|
TEST_ASSERT_NULL(strstr(resp.body, "geheim123"));
|
||||||
|
o = cJSON_Parse(resp.body);
|
||||||
|
sa = cJSON_GetObjectItemCaseSensitive(o, "standalone");
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(sa, "enabled")));
|
||||||
|
TEST_ASSERT_EQUAL_STRING("Wohnzimmerlampe",
|
||||||
|
cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(sa, "ssid")));
|
||||||
|
TEST_ASSERT_EQUAL_INT(11, (int)cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(sa, "channel")));
|
||||||
|
TEST_ASSERT_FALSE(cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(sa, "pulse")));
|
||||||
|
cJSON_Delete(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ohne eigenen Namen zeigt die Antwort den WIRKSAMEN, nicht einen leeren String -
|
||||||
|
* sonst muesste jeder Aufrufer die Vorgabe selbst nachbilden. */
|
||||||
|
static void test_settings_show_the_effective_ap_name(void)
|
||||||
|
{
|
||||||
|
cJSON *o, *sa;
|
||||||
|
fake_settings.ap_ssid[0] = '\0';
|
||||||
|
call(NL_HTTP_GET, "/api/v1/system/settings", TOKEN, NULL);
|
||||||
|
o = cJSON_Parse(resp.body);
|
||||||
|
sa = cJSON_GetObjectItemCaseSensitive(o, "standalone");
|
||||||
|
TEST_ASSERT_EQUAL_STRING("ninlight-681f",
|
||||||
|
cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(sa, "ssid")));
|
||||||
|
/* Kanal 0 im Datensatz heisst 6. */
|
||||||
|
TEST_ASSERT_EQUAL_INT(6, (int)cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(sa, "channel")));
|
||||||
|
cJSON_Delete(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "ap" allein reicht nicht: denselben Wert meldet der Onboarding-AP. Ohne dieses Feld
|
||||||
|
* boete die App einer fertig eingerichteten Lampe ein Onboarding an. */
|
||||||
|
static void test_info_tells_standalone_from_onboarding(void)
|
||||||
|
{
|
||||||
|
cJSON *o, *w;
|
||||||
|
fake_info.wifi_mode = "ap";
|
||||||
|
fake_info.wifi_standalone = true;
|
||||||
|
call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL);
|
||||||
|
o = cJSON_Parse(resp.body);
|
||||||
|
w = cJSON_GetObjectItemCaseSensitive(o, "wifi");
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsTrue(cJSON_GetObjectItemCaseSensitive(w, "standalone")));
|
||||||
|
cJSON_Delete(o);
|
||||||
|
|
||||||
|
fake_info.wifi_standalone = false;
|
||||||
|
call(NL_HTTP_GET, "/api/v1/system/info", NULL, NULL);
|
||||||
|
o = cJSON_Parse(resp.body);
|
||||||
|
w = cJSON_GetObjectItemCaseSensitive(o, "wifi");
|
||||||
|
TEST_ASSERT_TRUE(cJSON_IsFalse(cJSON_GetObjectItemCaseSensitive(w, "standalone")));
|
||||||
|
cJSON_Delete(o);
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
UNITY_BEGIN();
|
UNITY_BEGIN();
|
||||||
@@ -627,5 +790,16 @@ int main(void)
|
|||||||
RUN_TEST(test_info_exposes_sacn_state);
|
RUN_TEST(test_info_exposes_sacn_state);
|
||||||
RUN_TEST(test_info_reports_a_dead_sacn_task);
|
RUN_TEST(test_info_reports_a_dead_sacn_task);
|
||||||
RUN_TEST(test_commands);
|
RUN_TEST(test_commands);
|
||||||
|
RUN_TEST(test_standalone_requires_a_password);
|
||||||
|
RUN_TEST(test_standalone_keeps_a_stored_password);
|
||||||
|
RUN_TEST(test_standalone_rejects_a_short_password);
|
||||||
|
RUN_TEST(test_standalone_rejects_a_channel_outside_the_band);
|
||||||
|
RUN_TEST(test_standalone_accepts_a_full_request);
|
||||||
|
RUN_TEST(test_standalone_can_be_switched_off);
|
||||||
|
RUN_TEST(test_standalone_reports_a_busy_radio_and_a_failed_save);
|
||||||
|
RUN_TEST(test_standalone_rejects_bad_types_of_the_other_fields);
|
||||||
|
RUN_TEST(test_settings_show_standalone_without_the_password);
|
||||||
|
RUN_TEST(test_settings_show_the_effective_ap_name);
|
||||||
|
RUN_TEST(test_info_tells_standalone_from_onboarding);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user