Skip to content

Commit 97dee57

Browse files
authored
Merge pull request #94 from baba-dev/codex/refactor-room-fixtures-into-provider
feat(rooms): add integration rooms provider
2 parents 0df4464 + 3188438 commit 97dee57

7 files changed

Lines changed: 207 additions & 55 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
#include "rooms_provider.h"
7+
8+
#include <stddef.h>
9+
10+
static room_entity_t ENT_BAKERY_MAIN = {
11+
.entity_id = "light.bakery_main",
12+
.kind = ROOM_ENTITY_LIGHT,
13+
.available = true,
14+
.on = false,
15+
.value = -1,
16+
};
17+
18+
static room_entity_t ENT_BEDROOM_MAIN = {
19+
.entity_id = "light.bedroom_main",
20+
.kind = ROOM_ENTITY_LIGHT,
21+
.available = true,
22+
.on = true,
23+
.value = 75,
24+
};
25+
26+
static room_entity_t ENT_LIVING_MAIN = {
27+
.entity_id = "light.living_main",
28+
.kind = ROOM_ENTITY_LIGHT,
29+
.available = true,
30+
.on = false,
31+
.value = -1,
32+
};
33+
34+
static room_entity_t* ROOM0_ENTS[] = {&ENT_BAKERY_MAIN};
35+
static room_entity_t* ROOM1_ENTS[] = {&ENT_BEDROOM_MAIN};
36+
static room_entity_t* ROOM2_ENTS[] = {&ENT_LIVING_MAIN};
37+
38+
static room_t ROOMS[] = {
39+
{
40+
.room_id = "bakery",
41+
.name = "Bakery",
42+
.entities = (room_entity_t**)ROOM0_ENTS,
43+
.entity_count = sizeof(ROOM0_ENTS) / sizeof(ROOM0_ENTS[0]),
44+
.temp_c = 24,
45+
.humidity = 48,
46+
},
47+
{
48+
.room_id = "bedroom",
49+
.name = "Bedroom",
50+
.entities = (room_entity_t**)ROOM1_ENTS,
51+
.entity_count = sizeof(ROOM1_ENTS) / sizeof(ROOM1_ENTS[0]),
52+
.temp_c = 23,
53+
.humidity = 50,
54+
},
55+
{
56+
.room_id = "living",
57+
.name = "Living Room",
58+
.entities = (room_entity_t**)ROOM2_ENTS,
59+
.entity_count = sizeof(ROOM2_ENTS) / sizeof(ROOM2_ENTS[0]),
60+
.temp_c = 25,
61+
.humidity = 45,
62+
},
63+
};
64+
65+
static rooms_state_t DEFAULT_STATE = {
66+
.rooms = ROOMS,
67+
.room_count = sizeof(ROOMS) / sizeof(ROOMS[0]),
68+
};
69+
70+
static const rooms_state_t* s_current_state = &DEFAULT_STATE;
71+
72+
const rooms_state_t* rooms_provider_get_state(void)
73+
{
74+
return s_current_state;
75+
}
76+
77+
void rooms_provider_set_state(const rooms_state_t* state)
78+
{
79+
s_current_state = state;
80+
}
81+
82+
void rooms_provider_reset_state(void)
83+
{
84+
s_current_state = &DEFAULT_STATE;
85+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
#pragma once
7+
8+
#include "../ui/pages/ui_rooms_model.h"
9+
10+
#ifdef __cplusplus
11+
extern "C"
12+
{
13+
#endif
14+
15+
/**
16+
* @brief Retrieve the current rooms state snapshot.
17+
*
18+
* The pointer remains owned by the provider. Callers should treat the
19+
* returned data as read-only and copy it if a longer lifetime is needed.
20+
*/
21+
const rooms_state_t* rooms_provider_get_state(void);
22+
23+
/**
24+
* @brief Replace the active rooms state snapshot.
25+
*
26+
* Passing NULL clears the current snapshot so consumers can reset their
27+
* views while awaiting new data.
28+
*/
29+
void rooms_provider_set_state(const rooms_state_t* state);
30+
31+
/**
32+
* @brief Restore the provider's built-in mock snapshot.
33+
*/
34+
void rooms_provider_reset_state(void);
35+
36+
#ifdef __cplusplus
37+
}
38+
#endif

custom/ui/pages/ui_page_rooms.c

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdbool.h>
99
#include <string.h>
1010

11+
#include "../../integration/rooms_provider.h"
1112
#include "../ui_theme.h"
1213
#include "../ui_wallpaper.h"
1314
#include "../widgets/ui_room_card.h"
@@ -45,60 +46,6 @@ typedef struct
4546

4647
static ui_page_rooms_ctx_t* s_ctx = NULL;
4748

48-
static room_entity_t ENT_BAKERY_MAIN = {
49-
.entity_id = "light.bakery_main",
50-
.kind = ROOM_ENTITY_LIGHT,
51-
.available = true,
52-
.on = false,
53-
.value = -1,
54-
};
55-
56-
static room_entity_t ENT_BEDROOM_MAIN = {
57-
.entity_id = "light.bedroom_main",
58-
.kind = ROOM_ENTITY_LIGHT,
59-
.available = true,
60-
.on = true,
61-
.value = 75,
62-
};
63-
64-
static room_entity_t ENT_LIVING_MAIN = {
65-
.entity_id = "light.living_main",
66-
.kind = ROOM_ENTITY_LIGHT,
67-
.available = true,
68-
.on = false,
69-
.value = -1,
70-
};
71-
72-
static room_entity_t* ROOM0_ENTS[] = {&ENT_BAKERY_MAIN};
73-
static room_entity_t* ROOM1_ENTS[] = {&ENT_BEDROOM_MAIN};
74-
static room_entity_t* ROOM2_ENTS[] = {&ENT_LIVING_MAIN};
75-
76-
static room_t ROOMS[] = {
77-
{.room_id = "bakery",
78-
.name = "Bakery",
79-
.entities = (room_entity_t**)ROOM0_ENTS,
80-
.entity_count = 1,
81-
.temp_c = 24,
82-
.humidity = 48},
83-
{.room_id = "bedroom",
84-
.name = "Bedroom",
85-
.entities = (room_entity_t**)ROOM1_ENTS,
86-
.entity_count = 1,
87-
.temp_c = 23,
88-
.humidity = 50},
89-
{.room_id = "living",
90-
.name = "Living Room",
91-
.entities = (room_entity_t**)ROOM2_ENTS,
92-
.entity_count = 1,
93-
.temp_c = 25,
94-
.humidity = 45},
95-
};
96-
97-
static rooms_state_t INITIAL_STATE = {
98-
.rooms = ROOMS,
99-
.room_count = sizeof(ROOMS) / sizeof(ROOMS[0]),
100-
};
101-
10249
static void ui_page_rooms_delete_cb(lv_event_t* event)
10350
{
10451
if (event == NULL)
@@ -395,7 +342,7 @@ lv_obj_t* ui_page_rooms_create(lv_obj_t* parent)
395342

396343
s_ctx = ctx;
397344

398-
ui_page_rooms_set_state(&INITIAL_STATE);
345+
ui_page_rooms_set_state(rooms_provider_get_state());
399346
play_intro(ctx);
400347

401348
return page;

platforms/desktop/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ set(ROOMS_PAGE_SHARED_SRCS
9090
custom/ui/widgets/ui_room_card.c
9191
custom/ui/ui_theme.c
9292
custom/ui/ui_wallpaper.c
93+
custom/integration/rooms_provider.c
9394
)
9495

9596
add_executable(rooms_page_test ${ROOMS_PAGE_SHARED_SRCS} tests/ui/rooms_page_test.c)

tests/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,16 @@ endif()
5858
# -----------------------------
5959
add_library(ui_rooms_under_test
6060
${REPO_ROOT}/custom/ui/pages/ui_page_rooms.c
61+
${REPO_ROOT}/custom/ui/pages/ui_rooms_model.c
62+
${REPO_ROOT}/custom/ui/widgets/ui_room_card.c
63+
${REPO_ROOT}/custom/ui/ui_theme.c
6164
${REPO_ROOT}/custom/ui/ui_wallpaper.c
65+
${REPO_ROOT}/custom/integration/rooms_provider.c
6266
)
6367
target_include_directories(ui_rooms_under_test PUBLIC
6468
${REPO_ROOT}/custom/ui
6569
${REPO_ROOT}/custom/ui/pages
70+
${REPO_ROOT}/custom/integration
6671
)
6772
target_link_libraries(ui_rooms_under_test PUBLIC lvgl::lvgl lvgl_config)
6873

tests/ui/rooms_page_snapshot.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <string.h>
99

1010
#include "custom/ui/pages/ui_page_rooms.h"
11+
#include "integration/rooms_provider.h"
1112
#include "lvgl.h"
1213

1314
#define SNAP_SCREEN_WIDTH 1280
@@ -50,6 +51,8 @@ int main(void)
5051
lv_obj_t* screen = lv_screen_active();
5152
lv_obj_clean(screen);
5253

54+
rooms_provider_reset_state();
55+
5356
lv_obj_t* page = ui_page_rooms_create(screen);
5457
if (page == NULL)
5558
{

tests/ui/rooms_page_test.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <string.h>
1010

1111
#include "custom/ui/pages/ui_page_rooms.h"
12+
#include "integration/rooms_provider.h"
1213
#include "lvgl.h"
1314

1415
#define TEST_SCREEN_WIDTH 1280
@@ -101,6 +102,8 @@ int main(void)
101102
lv_obj_t* screen = lv_screen_active();
102103
lv_obj_clean(screen);
103104

105+
rooms_provider_reset_state();
106+
104107
lv_obj_t* page = ui_page_rooms_create(screen);
105108
if (page == NULL)
106109
{
@@ -142,6 +145,76 @@ int main(void)
142145
}
143146
}
144147

148+
room_entity_t bakery_main = {
149+
.entity_id = "light.bakery_main",
150+
.kind = ROOM_ENTITY_LIGHT,
151+
.available = true,
152+
.on = true,
153+
.value = 10,
154+
};
155+
room_entity_t bedroom_main = {
156+
.entity_id = "light.bedroom_main",
157+
.kind = ROOM_ENTITY_LIGHT,
158+
.available = true,
159+
.on = false,
160+
.value = -1,
161+
};
162+
room_entity_t living_scene = {
163+
.entity_id = "switch.living_scene",
164+
.kind = ROOM_ENTITY_SWITCH,
165+
.available = true,
166+
.on = true,
167+
.value = -1,
168+
};
169+
170+
room_entity_t* bakery_entities[] = {&bakery_main};
171+
room_entity_t* bedroom_entities[] = {&bedroom_main};
172+
room_entity_t* living_entities[] = {&living_scene};
173+
174+
room_t updated_rooms[] = {
175+
{.room_id = "bakery",
176+
.name = "Bakery",
177+
.entities = bakery_entities,
178+
.entity_count = 1,
179+
.temp_c = 22,
180+
.humidity = 41},
181+
{.room_id = "bedroom",
182+
.name = "Bedroom",
183+
.entities = bedroom_entities,
184+
.entity_count = 1,
185+
.temp_c = 21,
186+
.humidity = 46},
187+
{.room_id = "living",
188+
.name = "Living Room",
189+
.entities = living_entities,
190+
.entity_count = 1,
191+
.temp_c = 24,
192+
.humidity = 44},
193+
};
194+
195+
rooms_state_t updated_state = {
196+
.rooms = updated_rooms,
197+
.room_count = sizeof(updated_rooms) / sizeof(updated_rooms[0]),
198+
};
199+
200+
rooms_provider_set_state(&updated_state);
201+
ui_page_rooms_set_state(rooms_provider_get_state());
202+
203+
lv_obj_t* living_toggle = ui_page_rooms_get_toggle("living");
204+
if (!ensure(living_toggle != NULL, "Living toggle missing after update"))
205+
{
206+
return 1;
207+
}
208+
lv_obj_send_event(living_toggle, LV_EVENT_CLICKED, NULL);
209+
if (!ensure(capture.last_entity != NULL
210+
&& strcmp(capture.last_entity, "switch.living_scene") == 0,
211+
"Updated entity id not reflected"))
212+
{
213+
return 1;
214+
}
215+
216+
rooms_provider_reset_state();
217+
145218
for (size_t i = 0; i < k_room_count; i++)
146219
{
147220
lv_obj_t* card = ui_page_rooms_get_card(room_ids[i]);

0 commit comments

Comments
 (0)