Skip to content

Web UI improvements #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 47 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
36cbba0
web: basic artnet view
SpComb Dec 26, 2024
3ae0512
web: basic artnet refresh
SpComb Dec 26, 2024
9ce891c
artnet: report input/output tick as ms interval
SpComb Dec 26, 2024
4634de4
artnet: api inputs, outputs
SpComb Dec 26, 2024
df20106
web: load artnet inputs, outputs
SpComb Dec 26, 2024
9af45f0
main leds: change api to return object, not array
SpComb Dec 26, 2024
55cdd51
web: percentage filter
SpComb Dec 26, 2024
2977dce
web: leds view with basic options + limit status
SpComb Dec 26, 2024
d21ab42
leds: use the same limit status terminology for cli/web
SpComb Dec 26, 2024
0be568a
leds: update interval, active bool
SpComb Dec 26, 2024
fa64970
artnet/leds: fix portTICK_RATE_MS calc
SpComb Dec 26, 2024
3f07ab7
leds: status test_mode
SpComb Dec 26, 2024
dd3eede
leds: artnet info
SpComb Dec 26, 2024
bc8783c
leds: artnet dmx status
SpComb Dec 26, 2024
21b27ec
web: tabbed view centered by class
SpComb Dec 26, 2024
e275fc2
main: split leds_http_post.c
SpComb Dec 26, 2024
5745529
main: leds status api
SpComb Dec 26, 2024
1c8293b
web: refresh leds status
SpComb Dec 26, 2024
e52b09e
leds api: check http_request_query err
SpComb Dec 29, 2024
c117287
http: user leds status
SpComb Jan 6, 2025
e76c2e6
gitignore builds, debug
SpComb Jan 6, 2025
36fb648
TICK_MS
SpComb Jan 6, 2025
651e554
user: initial states, export str methods
SpComb Jan 6, 2025
0ad3d51
user: static const user leds state lookup tables
SpComb Jan 6, 2025
bf87008
main: store last user state/activity/alert state
SpComb Jan 6, 2025
884db4a
web: indent fix
SpComb Jan 6, 2025
b5cfd12
main: user power log
SpComb Jan 6, 2025
2e1c885
web: interval rounding
SpComb Jan 6, 2025
ccfc0f7
web: timestamp filter
SpComb Jan 6, 2025
c21e972
web: main view for user status
SpComb Jan 6, 2025
bd84718
web home: fix status led names to match API
SpComb Jan 6, 2025
cfbb6c7
leds: differentiate leds_update() activity types
SpComb Jan 6, 2025
ad95dc9
leds: differentiate USER_ACTIVITY_LEDS_ARTNET_TIMEOUT
SpComb Jan 6, 2025
b9ee7b6
leds: silent update timeout
SpComb Jan 6, 2025
ca83de5
leds_test: fix stuck active on pause or after TEST_MODE_BLACK
SpComb Jan 6, 2025
fa19350
main: user button API
SpComb Jan 6, 2025
448773b
main: user button API returns status
SpComb Jan 6, 2025
786c52c
web: fix home status loading
SpComb Jan 6, 2025
a1a1df2
web: basic config/test button click
SpComb Jan 6, 2025
19b4f2b
web: fix centered views, responsive split/fieldset layouts
SpComb Jan 6, 2025
6949441
web: button component
SpComb Jan 6, 2025
ee8dcd4
main: clarify button POST logging
SpComb Jan 6, 2025
b75d60d
web: button press/hold/release
SpComb Jan 6, 2025
0f6f6bf
web: move config apply to top controls
SpComb Jan 6, 2025
6377e49
web: fixup portrait fieldset layout to keep fourth column
SpComb Jan 6, 2025
5efb026
main: delay restart to give HTTP POST response a chance
SpComb Jan 6, 2025
498c909
web: restart on config apply
SpComb Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
/projects/*/sdkconfig@*
/projects/*/sdkconfig.old
/projects/*/build/

builds/
debug/
42 changes: 38 additions & 4 deletions components/leds/include/leds_status.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,30 @@ struct leds_limit_status {
unsigned output; /* Limited LED power output */
};

/*
* Get power usage before configured limits.
*
* @return 0.0 .. 1.0
* 0.0 -> all off
* 1.0 -> maximum power
*/
static inline float leds_limit_status_power(const struct leds_limit_status *status)
{
if (status->power && status->count) {
return (float) status->power / (float) status->count;
} else {
return 0.0f;
}
}

/*
* Get power limit configured.
*
* @return 0.0 .. 1.0
* 0.0 -> maximum power limit
* 1.0 -> no power limit
*/
static inline float leds_limit_status_configured(const struct leds_limit_status *status)
static inline float leds_limit_status_limit(const struct leds_limit_status *status)
{
if (status->limit && status->count) {
return (float) status->limit / (float) status->count;
Expand All @@ -33,7 +49,7 @@ static inline float leds_limit_status_configured(const struct leds_limit_status
* 1.0 -> at power limit
* >1.0 -> power limiting active
*/
static inline float leds_limit_status_utilization(const struct leds_limit_status *status)
static inline float leds_limit_status_util(const struct leds_limit_status *status)
{
if (status->limit) {
return (float) status->power / (float) status->limit;
Expand All @@ -43,19 +59,37 @@ static inline float leds_limit_status_utilization(const struct leds_limit_status
}

/*
* Get power limit applied.
* Get applied output power limit.
*
* This is applied using integer math internally, the floating point value is an approximation.
*
* @return 0.0 .. 1.0, with 1.0 meaning power is not being limited and numbers closer to 0.0 meaning more power limiting is being applied.
*/
static inline float leds_limit_status_active(const struct leds_limit_status *status)
static inline float leds_limit_status_applied(const struct leds_limit_status *status)
{
if (status->power) {
return (float) status->output / (float) status->power;
} else {
return 1.0f;
}

}
/*
* Get output power used.
*
* This is applied using integer math internally, the floating point value is an approximation.
*
* @return 0.0 .. 1.0
* 0.0 -> all LEDs are off, minimum output power
* 1.0 -> at power limit
*/
static inline float leds_limit_status_output(const struct leds_limit_status *status)
{
if (status->limit) {
return (float) status->output / (float) status->limit;
} else {
return 0.0f;
}
}

void leds_get_limit_total_status(struct leds *leds, struct leds_limit_status *total_status);
Expand Down
10 changes: 6 additions & 4 deletions main/artnet_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,18 @@ int artnet_cmd_info(int argc, char **argv, void *ctx)
for (int i = 0; i < inputs_size && i < ARTNET_INPUTS_MAX; i++) {
struct artnet_input_options *options = &artnet_input_options[i];
struct artnet_input_state state;
TickType_t tick = xTaskGetTickCount();

if ((err = artnet_get_input_state(artnet, i, &state))) {
LOG_ERROR("artnet_get_input_state");
continue;
}

printf("\t%2d: port=%1d index=%3u @ net %3u subnet %2u universe %2u: len %3u\n", i,
printf("\t%2d: port=%1d index=%3u @ net %3u subnet %2u universe %2u: len %3u @ %d ms\n", i,
options->port, options->index,
artnet_address_net(options->address), artnet_address_subnet(options->address), artnet_address_universe(options->address),
state.len
state.len,
state.tick ? (tick - state.tick) / portTICK_RATE_MS : 0
);
}

Expand All @@ -75,15 +77,15 @@ int artnet_cmd_info(int argc, char **argv, void *ctx)
continue;
}

printf("\t%2d: port=%1d index=%3u @ net %3u subnet %2u universe %2u -> %16.16s[%3u]: seq %3u @ %d ticks\n", i,
printf("\t%2d: port=%1d index=%3u @ net %3u subnet %2u universe %2u -> %16.16s[%3u]: seq %3u @ %d ms\n", i,
options->port, options->index,
artnet_address_net(options->address),
artnet_address_subnet(options->address),
artnet_address_universe(options->address),
options->name,
options->index,
state.seq,
state.tick ? tick - state.tick : 0
state.tick ? (tick - state.tick) * portTICK_RATE_MS : 0
);
}

Expand Down
78 changes: 74 additions & 4 deletions main/artnet_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
#include <logging.h>
#include <json.h>

#define TICK_MS(current_tick, tick) (tick ? (current_tick - tick) * portTICK_RATE_MS : 0)

static int artnet_api_write_input_object(struct json_writer *w, const struct artnet_input_options *options, const struct artnet_input_state *state)
{
TickType_t tick = xTaskGetTickCount();

return (
JSON_WRITE_MEMBER_UINT(w, "port", options->port)
|| JSON_WRITE_MEMBER_UINT(w, "index", options->index)
Expand All @@ -19,13 +23,15 @@ static int artnet_api_write_input_object(struct json_writer *w, const struct art
|| JSON_WRITE_MEMBER_UINT(w, "universe", artnet_address_universe(options->address))
|| JSON_WRITE_MEMBER_OBJECT(w, "state",
JSON_WRITE_MEMBER_UINT(w, "tick", state->tick)
|| JSON_WRITE_MEMBER_UINT(w, "tick_ms", TICK_MS(tick, state->tick))
|| JSON_WRITE_MEMBER_UINT(w, "len", state->len)
)
);
}

static int artnet_api_write_inputs_array(struct json_writer *w)
static int artnet_api_write_inputs_array(struct json_writer *w, void *ctx)
{
struct artnet *artnet = ctx;
struct artnet_input_options options;
struct artnet_input_state state;
int err;
Expand All @@ -50,6 +56,8 @@ static int artnet_api_write_inputs_array(struct json_writer *w)

static int artnet_api_write_output_object(struct json_writer *w, const struct artnet_output_options *options, const struct artnet_output_state *state)
{
TickType_t tick = xTaskGetTickCount();

return (
JSON_WRITE_MEMBER_UINT(w, "port", options->port)
|| JSON_WRITE_MEMBER_UINT(w, "index", options->index)
Expand All @@ -59,14 +67,16 @@ static int artnet_api_write_output_object(struct json_writer *w, const struct ar
|| JSON_WRITE_MEMBER_UINT(w, "universe", artnet_address_universe(options->address))
|| JSON_WRITE_MEMBER_OBJECT(w, "state",
JSON_WRITE_MEMBER_UINT(w, "tick", state->tick)
|| JSON_WRITE_MEMBER_UINT(w, "tick_ms", TICK_MS(tick, state->tick))
|| JSON_WRITE_MEMBER_UINT(w, "seq", state->seq)
)
);
}


static int artnet_api_write_outputs_array(struct json_writer *w)
static int artnet_api_write_outputs_array(struct json_writer *w, void *ctx)
{
struct artnet *artnet = ctx;
struct artnet_output_options options;
struct artnet_output_state state;
int err;
Expand All @@ -89,6 +99,20 @@ static int artnet_api_write_outputs_array(struct json_writer *w)
return 0;
}

static int artnet_api_write_inputs(struct json_writer *w, void *ctx)
{
struct artnet *artnet = ctx;

return JSON_WRITE_ARRAY(w, artnet_api_write_inputs_array(w, artnet));
}

static int artnet_api_write_outputs(struct json_writer *w, void *ctx)
{
struct artnet *artnet = ctx;

return JSON_WRITE_ARRAY(w, artnet_api_write_outputs_array(w, artnet));
}

static int artnet_api_write(struct json_writer *w, void *ctx)
{
struct artnet *artnet = ctx;
Expand Down Expand Up @@ -118,8 +142,8 @@ static int artnet_api_write(struct json_writer *w, void *ctx)
|| JSON_WRITE_MEMBER_STRING(w, "short_name", options.metadata.short_name)
|| JSON_WRITE_MEMBER_STRING(w, "long_name", options.metadata.long_name)
)
|| JSON_WRITE_MEMBER_ARRAY(w, "inputs", artnet_api_write_inputs_array(w))
|| JSON_WRITE_MEMBER_ARRAY(w, "outputs", artnet_api_write_outputs_array(w))
|| JSON_WRITE_MEMBER_ARRAY(w, "inputs", artnet_api_write_inputs_array(w, artnet))
|| JSON_WRITE_MEMBER_ARRAY(w, "outputs", artnet_api_write_outputs_array(w, artnet))
);
}

Expand All @@ -144,3 +168,49 @@ int artnet_api_handler(struct http_request *request, struct http_response *respo

return 0;
}

int artnet_api_inputs_handler(struct http_request *request, struct http_response *response, void *ctx)
{
int err;

if ((err = http_request_headers(request, NULL))) {
LOG_WARN("http_request_headers");
return err;
}

if (!artnet) {
// disabled
return HTTP_NO_CONTENT;
}

if ((err = write_http_response_json(response, artnet_api_write_inputs, artnet))) {
LOG_WARN("write_http_response_json -> artnet_api_write_inputs");
return err;
}

return 0;

}

int artnet_api_outputs_handler(struct http_request *request, struct http_response *response, void *ctx)
{
int err;

if ((err = http_request_headers(request, NULL))) {
LOG_WARN("http_request_headers");
return err;
}

if (!artnet) {
// disabled
return HTTP_NO_CONTENT;
}

if ((err = write_http_response_json(response, artnet_api_write_outputs, artnet))) {
LOG_WARN("write_http_response_json -> artnet_api_write_outputs");
return err;
}

return 0;

}
8 changes: 8 additions & 0 deletions main/http_routes.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,20 @@ const struct http_route http_routes[] = {

/* artnet_http.c */
{ "GET", "api/artnet", artnet_api_handler, NULL },
{ "GET", "api/artnet/inputs", artnet_api_inputs_handler, NULL },
{ "GET", "api/artnet/outputs", artnet_api_outputs_handler, NULL },

/* leds_http.c */
{ "GET", "api/leds", leds_api_get, NULL },
{ "GET", "api/leds/status", leds_api_get_status, NULL },
{ "POST", "api/leds", leds_api_post, NULL },

{ "GET", "api/leds/test", leds_api_test_get, NULL },
{ "POST", "api/leds/test", leds_api_test_post, NULL },

/* user_http.c */
{ "GET", "api/status", user_api_get_status, NULL },
{ "POST", "api/button", user_api_post_button, NULL },

{}
};
7 changes: 7 additions & 0 deletions main/http_routes.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,17 @@ int wifi_api_scan_handler(struct http_request *request, struct http_response *re

/* artnet_http.c */
int artnet_api_handler(struct http_request *request, struct http_response *response, void *ctx);
int artnet_api_inputs_handler(struct http_request *request, struct http_response *response, void *ctx);
int artnet_api_outputs_handler(struct http_request *request, struct http_response *response, void *ctx);

/* leds_http.c */
int leds_api_get(struct http_request *request, struct http_response *response, void *ctx);
int leds_api_get_status(struct http_request *request, struct http_response *response, void *ctx);
int leds_api_post(struct http_request *request, struct http_response *response, void *ctx);

int leds_api_test_get(struct http_request *request, struct http_response *response, void *ctx);
int leds_api_test_post(struct http_request *request, struct http_response *response, void *ctx);

/* user_http.c */
int user_api_get_status(struct http_request *request, struct http_response *response, void *ctx);
int user_api_post_button(struct http_request *request, struct http_response *response, void *ctx);
6 changes: 4 additions & 2 deletions main/leds.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void clear_leds_active(struct leds_state *state)
clear_atx_psu_bit(ATX_PSU_BIT_LEDS1 + state->index);
}

int update_leds(struct leds_state *state)
int update_leds(struct leds_state *state, enum user_activity leds_activity)
{
int err;

Expand All @@ -192,7 +192,9 @@ int update_leds(struct leds_state *state)
return err;
}

user_activity(USER_ACTIVITY_LEDS);
if (leds_activity) {
user_activity(leds_activity);
}

if ((err = leds_tx(state->leds))) {
LOG_ERROR("leds_tx");
Expand Down
14 changes: 11 additions & 3 deletions main/leds_artnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ int leds_artnet_update(struct leds_state *state, EventBits_t event_bits)

bool sync_mode = false;
bool update = false;
bool timeout = false;

if (state->test) {
if (data || sync) {
Expand Down Expand Up @@ -341,15 +342,16 @@ int leds_artnet_update(struct leds_state *state, EventBits_t event_bits)

// timeouts
if (data || sync) {
state->artnet->dmx_tick = xTaskGetTickCount();
leds_artnet_timeout_reset(state);
} else if (state->artnet->timeout_tick) {
if (xTaskGetTickCount() >= state->artnet->timeout_tick) {
timeout = true;

if (leds_artnet_timeout(state)) {
LOG_WARN("leds_artnet_timeout");
}

update = true;

// repeat
leds_artnet_timeout_reset(state);
}
Expand All @@ -359,7 +361,13 @@ int leds_artnet_update(struct leds_state *state, EventBits_t event_bits)
leds_artnet_sync_reset(state);
}

return update;
if (timeout) {
return LEDS_ARTNET_UPDATE_TIMEOUT;
} else if (update) {
return LEDS_ARTNET_UPDATE;
} else {
return 0;
}
}

int init_leds_artnet(struct leds_state *state, int index, const struct leds_config *config)
Expand Down
4 changes: 4 additions & 0 deletions main/leds_artnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct leds_artnet_state {
unsigned universe_count;
unsigned universe_leds_count;

TickType_t dmx_tick; // last dmx frame
struct artnet_dmx dmx;
struct artnet_output **outputs;

Expand All @@ -37,3 +38,6 @@ bool leds_artnet_active(struct leds_state *state, EventBits_t event_bits);

/* Update LEDs from artnet outputs */
int leds_artnet_update(struct leds_state *state, EventBits_t event_bits);

#define LEDS_ARTNET_UPDATE 1
#define LEDS_ARTNET_UPDATE_TIMEOUT 2
Loading