blob: a4d4daba5206fdab95bd2046f57fa32378f4f1af (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include "state_machine.h"
#include "esp_check.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "display.h"
#include "local_screens.h"
#include "state_client.h"
static const char *TAG = "state";
static esp_timer_handle_t s_idle_timer;
static void arm_idle_timer_unlocked(void)
{
viewport_state_lock();
uint32_t ms = viewport_state_get()->idle_timeout_ms;
viewport_state_unlock();
if (ms == 0) return;
esp_timer_stop(s_idle_timer);
esp_timer_start_once(s_idle_timer, (uint64_t)ms * 1000ULL);
}
static void disarm_idle_timer(void)
{
esp_timer_stop(s_idle_timer);
}
static void idle_timer_fired(void *arg)
{
ESP_LOGI(TAG, "idle timer expired — sleeping");
state_machine_set_local(VIEWPORT_STATE_ASLEEP);
}
esp_err_t state_machine_init(void)
{
esp_timer_create_args_t args = {
.callback = &idle_timer_fired,
.name = "viewport_idle",
};
return esp_timer_create(&args, &s_idle_timer);
}
esp_err_t state_machine_set(viewport_run_state_t target)
{
if (target != VIEWPORT_STATE_AWAKE && target != VIEWPORT_STATE_ASLEEP)
return ESP_ERR_INVALID_ARG;
viewport_state_lock();
viewport_state_t *st = viewport_state_get();
if (st->state == target) {
viewport_state_unlock();
return ESP_OK; // idempotent no-op
}
st->state = target;
bool configured = st->configured;
viewport_state_unlock();
if (target == VIEWPORT_STATE_AWAKE) {
if (display_is_up()) {
display_wake();
// Content choice: a configured device shows "Loading…" until
// Scrypted pushes a /frame; a device with no scrypted URL
// shows the info screen since there's no Scrypted to push.
if (configured) local_screens_show_loading();
else local_screens_show_info();
}
arm_idle_timer_unlocked();
ESP_LOGI(TAG, "AWAKE (%s)", configured ? "configured" : "no scrypted URL");
} else {
disarm_idle_timer();
if (display_is_up()) display_sleep();
ESP_LOGI(TAG, "ASLEEP");
}
return ESP_OK;
}
void state_machine_frame_painted(void)
{
viewport_state_lock();
bool awake = (viewport_state_get()->state == VIEWPORT_STATE_AWAKE);
viewport_state_unlock();
if (awake) arm_idle_timer_unlocked();
}
void state_machine_set_local(viewport_run_state_t target)
{
esp_err_t err = state_machine_set(target);
if (err != ESP_OK) return;
// Only POST when there's a Scrypted to talk to. Without a scrypted URL,
// tap toggles change the local display state without notifying anyone.
viewport_state_lock();
bool configured = viewport_state_get()->configured;
viewport_state_unlock();
if (configured) state_client_post(target);
}
viewport_run_state_t state_machine_current(void)
{
viewport_state_lock();
viewport_run_state_t s = viewport_state_get()->state;
viewport_state_unlock();
return s;
}
|