Show a spinner while a screen starts and while a camera loads, bring a camera's first picture sooner, and round the alert's camera picture (0.2.87)
Starting screen: until the first layout, render() keeps the status text
("Connecting to Home Assistant", "Waiting for ESP Screens") and a spinner
as one block in the middle of the page; the first layout deletes both.
The room label stays empty meanwhile, and ROOM_NAME defaults to "".
Camera: the full screen shows a spinner instead of "Loading image". The
screen asks when the camera opens and loads a link as soon as it comes
(camera_load, never under a finger) instead of waiting for the 250 ms
tick twice, and online_image reads 16 KB per loop instead of 4 KB. On the
bench Guition with the EZVIZ camera: cold 5.8 -> 4.55 s, warm 3.4 -> 2.06 s.
Alert picture: the image takes the frame's radius (18, the alert card's);
LVGL's software renderer clips it row by row, without a layer.
One spinner_create() makes the busy sheet's, the starting screen's and the
camera's spinner; theme role CAMERA_TRACK colours the camera's ring. The
README gets a row of camera pictures; docs/CAMERA.md, RELEASING.md and
TEST_RESULTS_0287.md describe the measurements.
Checked with tools/check.sh (473 Python tests, 19/19 C++, editor) and
--firmware: CYD 1,678,816 B (91.5 %, +1,312 B), Guition 2,055,280 B
(25.3 %). Host renders of both boards in both looks; four OTA builds on
the bench Guition Wallbox, which runs this firmware.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,21 @@ class Rules(unittest.TestCase):
|
||||
config = (ROOT / 'screen_manager/config.yaml').read_text()
|
||||
self.assertIn(f'{camera_feed.PORT}/tcp: {camera_feed.PORT}', config)
|
||||
|
||||
def test_the_first_picture_waits_for_no_tick(self):
|
||||
# Firmware 0.2.73+: the camera asks when it opens and loads the link when it comes, not on the next 250 ms tick;
|
||||
# the spinner turns until the first picture or a note is there.
|
||||
opened = TILES.split('inline void camera_open(const std::string &entity, const std::string &name) {', 1)[1].split('\n}\n', 1)[0]
|
||||
self.assertIn('camera_spinner = spinner_create(camera_root,', opened)
|
||||
self.assertIn('if (awake() && fresh() && camera.should_ask(now)) {', opened)
|
||||
answer = TILES.split('inline void camera_answer(const std::string &view, const std::string &entity, const std::string &url) {', 1)[1].split('\n}\n', 1)[0]
|
||||
self.assertIn('if (awake() && camera.should_load(now)) camera_load(now);', answer)
|
||||
# Never under a finger, from the answer or from the tick.
|
||||
load = TILES.split('inline void camera_load(uint32_t now) {', 1)[1].split('\n}\n', 1)[0]
|
||||
self.assertIn('lv_indev_get_state(input) == LV_INDEV_STATE_PRESSED) return;', load)
|
||||
note = TILES.split('inline void camera_note_text(const char *text) {', 1)[1].split('\n}\n', 1)[0]
|
||||
self.assertIn('lv_obj_delete(camera_spinner);', note)
|
||||
self.assertNotIn('Loading image', TILES)
|
||||
|
||||
|
||||
@unittest.skipUnless(HAS_PIL, 'Pillow comes with ESPHome in the add-on image')
|
||||
class Encoding(unittest.TestCase):
|
||||
|
||||
Reference in New Issue
Block a user