mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2026-10-31 22:02:17 +01:00
fix: deletes send their removal after the reply; test_reboot waits for the restart
- shadeRemoved, groupRemoved and roomRemoved went out from the deletes, before the edit's reply. They now come from editChanges and go out with the edit's other events, after it (test_adding_and_deleting_a_room). - test_reboot reconnected in the moment between the sockets closing and the restart, and waited for a hello that never came. It now waits, retries a connect without hello, and checks the uptime went back. e2e on the device (esp32s3dbg): 72 passed, 3 skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
17bb571635
commit
2c815d30f1
7 changed files with 53 additions and 20 deletions
|
|
@ -31,10 +31,9 @@ edit_changes_t editChanges(model_edit_type_t type, const edit_result_t &result)
|
||||||
case model_edit_type_t::unlink_repeater:
|
case model_edit_type_t::unlink_repeater:
|
||||||
c.repeaters = true;
|
c.repeaters = true;
|
||||||
break;
|
break;
|
||||||
case model_edit_type_t::delete_room:
|
case model_edit_type_t::delete_room: c.removedRoomId = result.id; break;
|
||||||
case model_edit_type_t::delete_shade:
|
case model_edit_type_t::delete_shade: c.removedShadeId = result.id; break;
|
||||||
case model_edit_type_t::delete_group:
|
case model_edit_type_t::delete_group: c.removedGroupId = result.id; break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,10 @@ struct edit_changes_t {
|
||||||
uint8_t roomId = 0;
|
uint8_t roomId = 0;
|
||||||
sort_list_t order = sort_list_t::none;
|
sort_list_t order = sort_list_t::none;
|
||||||
bool repeaters = false;
|
bool repeaters = false;
|
||||||
|
// A delete: the id of what was removed.
|
||||||
|
uint8_t removedShadeId = 0;
|
||||||
|
uint8_t removedGroupId = 0;
|
||||||
|
uint8_t removedRoomId = 0;
|
||||||
};
|
};
|
||||||
edit_changes_t editChanges(model_edit_type_t type, const edit_result_t &result);
|
edit_changes_t editChanges(model_edit_type_t type, const edit_result_t &result);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#include "ConfigFile.h"
|
#include "ConfigFile.h"
|
||||||
#include "ModelEditor.h"
|
#include "ModelEditor.h"
|
||||||
#include "ShadeChanges.h"
|
#include "ShadeChanges.h"
|
||||||
#include "outputs/ProtoSocket.h"
|
|
||||||
|
|
||||||
static const char *TAG = "Somfy";
|
static const char *TAG = "Somfy";
|
||||||
|
|
||||||
|
|
@ -291,7 +290,6 @@ bool SomfyShadeController::deleteShade(uint8_t shadeId) {
|
||||||
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
|
for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) {
|
||||||
if(this->shades[i].getShadeId() == shadeId) {
|
if(this->shades[i].getShadeId() == shadeId) {
|
||||||
shades[i].emitState("shadeRemoved");
|
shades[i].emitState("shadeRemoved");
|
||||||
protoSocket.shadeRemoved(shadeId);
|
|
||||||
shades[i].unpublish();
|
shades[i].unpublish();
|
||||||
this->shades[i].clear();
|
this->shades[i].clear();
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +320,6 @@ bool SomfyShadeController::deleteRoom(uint8_t roomId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rooms[i].emitState("roomRemoved");
|
rooms[i].emitState("roomRemoved");
|
||||||
protoSocket.roomRemoved(roomId);
|
|
||||||
this->rooms[i].clear();
|
this->rooms[i].clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +335,6 @@ bool SomfyShadeController::deleteGroup(uint8_t groupId) {
|
||||||
if(shade) shade->configChanged();
|
if(shade) shade->configChanged();
|
||||||
}
|
}
|
||||||
groups[i].emitState("groupRemoved");
|
groups[i].emitState("groupRemoved");
|
||||||
protoSocket.groupRemoved(groupId);
|
|
||||||
groups[i].unpublish();
|
groups[i].unpublish();
|
||||||
this->groups[i].clear();
|
this->groups[i].clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,9 @@ static void markEdited(const model_edit_t &edit, const edit_result_t &result) {
|
||||||
if(room) protoSocket.room(*room);
|
if(room) protoSocket.room(*room);
|
||||||
if(c.order != sort_list_t::none) protoSocket.order(c.order);
|
if(c.order != sort_list_t::none) protoSocket.order(c.order);
|
||||||
if(c.repeaters) protoSocket.repeaters();
|
if(c.repeaters) protoSocket.repeaters();
|
||||||
|
if(c.removedShadeId) protoSocket.shadeRemoved(c.removedShadeId);
|
||||||
|
if(c.removedGroupId) protoSocket.groupRemoved(c.removedGroupId);
|
||||||
|
if(c.removedRoomId) protoSocket.roomRemoved(c.removedRoomId);
|
||||||
}
|
}
|
||||||
void runModelEdit(model_edit_t *edit) {
|
void runModelEdit(model_edit_t *edit) {
|
||||||
const edit_result_t result = applyModelEdit(*edit);
|
const edit_result_t result = applyModelEdit(*edit);
|
||||||
|
|
|
||||||
|
|
@ -118,10 +118,14 @@ def test_a_frequency_scan_starts_and_ends(connect, schema):
|
||||||
def test_reboot(request, host, token, connect, schema):
|
def test_reboot(request, host, token, connect, schema):
|
||||||
if not request.config.getoption("--reboot"):
|
if not request.config.getoption("--reboot"):
|
||||||
pytest.skip("reboots the device: pass --reboot")
|
pytest.skip("reboots the device: pass --reboot")
|
||||||
c, _, _ = synced_model(connect, schema)
|
c = connect(schema=schema.hash)
|
||||||
|
_, frames, _ = run_sync(c)
|
||||||
|
uptime_before = uptime(schema, frames)
|
||||||
assert is_ok(schema, op(c, schema, "reboot", {}))
|
assert is_ok(schema, op(c, schema, "reboot", {}))
|
||||||
assert c.closed.wait(15), "the socket stayed open"
|
assert c.closed.wait(15), "the socket stayed open"
|
||||||
# Back once it answers a connect with hello again.
|
# The device closes its sockets just before it restarts, and may still
|
||||||
|
# take a connection in between: that one never gets its hello.
|
||||||
|
time.sleep(3)
|
||||||
end = time.time() + 90
|
end = time.time() + 90
|
||||||
while True:
|
while True:
|
||||||
assert time.time() < end, "the device didn't come back"
|
assert time.time() < end, "the device didn't come back"
|
||||||
|
|
@ -132,9 +136,19 @@ def test_reboot(request, host, token, connect, schema):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
if back.status == 101:
|
if back.status == 101:
|
||||||
hello, _, _ = run_sync(back)
|
hello, frames, _ = run_sync(back, timeout=10)
|
||||||
assert hello["d"]["sh"] == schema.hash
|
assert hello["d"]["sh"] == schema.hash
|
||||||
|
assert uptime(schema, frames) < uptime_before, "the device didn't restart"
|
||||||
return
|
return
|
||||||
|
except TimeoutError:
|
||||||
|
pass # not back yet
|
||||||
finally:
|
finally:
|
||||||
back.close()
|
back.close()
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
|
|
||||||
|
def uptime(schema, frames):
|
||||||
|
"""The uptime, in ms, from the status a sync ends with."""
|
||||||
|
key = schema.keys["status"]
|
||||||
|
status = next(f["d"][key] for f in frames if key in f["d"])
|
||||||
|
return schema.expand(status)["uptime"]
|
||||||
|
|
|
||||||
10
test/fixtures/proto2/sync.json
vendored
10
test/fixtures/proto2/sync.json
vendored
|
|
@ -1515,13 +1515,15 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Z": {
|
"Z": {
|
||||||
"fr": 148772,
|
"fr": 148760,
|
||||||
"mx": 77812,
|
"mx": 77812,
|
||||||
"mn": 99332,
|
"mn": 102424,
|
||||||
"to": 294616,
|
"to": 294616,
|
||||||
"up": 24633,
|
"up": 30144,
|
||||||
|
"lp": 2862,
|
||||||
|
"lx": 106737,
|
||||||
"sd": "ssid 72",
|
"sd": "ssid 72",
|
||||||
"sg": -51,
|
"sg": -52,
|
||||||
"ch": 6
|
"ch": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,16 +205,30 @@ static void test_a_repeater_edit_sends_the_repeaters() {
|
||||||
TEST_ASSERT_TRUE(editChanges(model_edit_type_t::unlink_repeater, resultFor(0)).repeaters);
|
TEST_ASSERT_TRUE(editChanges(model_edit_type_t::unlink_repeater, resultFor(0)).repeaters);
|
||||||
TEST_ASSERT_FALSE(editChanges(model_edit_type_t::save_room, resultFor(1)).repeaters);
|
TEST_ASSERT_FALSE(editChanges(model_edit_type_t::save_room, resultFor(1)).repeaters);
|
||||||
}
|
}
|
||||||
static void test_deletes_send_nothing_more() {
|
static void test_deletes_send_their_removal() {
|
||||||
// Their removals go out as they happen.
|
// After the reply, as every edit's events are, so a client waiting for the
|
||||||
for(model_edit_type_t t : {model_edit_type_t::delete_room, model_edit_type_t::delete_shade, model_edit_type_t::delete_group}) {
|
// reply doesn't read past it.
|
||||||
const edit_changes_t c = editChanges(t, resultFor(4));
|
const edit_changes_t room = editChanges(model_edit_type_t::delete_room, resultFor(4));
|
||||||
|
const edit_changes_t shade = editChanges(model_edit_type_t::delete_shade, resultFor(5));
|
||||||
|
const edit_changes_t group = editChanges(model_edit_type_t::delete_group, resultFor(6));
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(4, room.removedRoomId);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(5, shade.removedShadeId);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(6, group.removedGroupId);
|
||||||
|
for(const edit_changes_t &c : {room, shade, group}) {
|
||||||
|
// Nothing is left of it to send whole.
|
||||||
TEST_ASSERT_EQUAL_UINT8(0, c.shadeId);
|
TEST_ASSERT_EQUAL_UINT8(0, c.shadeId);
|
||||||
TEST_ASSERT_EQUAL_UINT8(0, c.groupId);
|
TEST_ASSERT_EQUAL_UINT8(0, c.groupId);
|
||||||
TEST_ASSERT_EQUAL_UINT8(0, c.roomId);
|
TEST_ASSERT_EQUAL_UINT8(0, c.roomId);
|
||||||
TEST_ASSERT_EQUAL(sort_list_t::none, c.order);
|
TEST_ASSERT_EQUAL(sort_list_t::none, c.order);
|
||||||
TEST_ASSERT_FALSE(c.repeaters);
|
TEST_ASSERT_FALSE(c.repeaters);
|
||||||
}
|
}
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, room.removedShadeId + room.removedGroupId);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, shade.removedRoomId + shade.removedGroupId);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, group.removedRoomId + group.removedShadeId);
|
||||||
|
}
|
||||||
|
static void test_other_edits_remove_nothing() {
|
||||||
|
const edit_changes_t c = editChanges(model_edit_type_t::save_room, resultFor(4));
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(0, c.removedRoomId + c.removedShadeId + c.removedGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
@ -249,6 +263,7 @@ int main(int argc, char **argv) {
|
||||||
RUN_TEST(test_a_room_edit_sends_the_room);
|
RUN_TEST(test_a_room_edit_sends_the_room);
|
||||||
RUN_TEST(test_a_sort_edit_sends_its_list);
|
RUN_TEST(test_a_sort_edit_sends_its_list);
|
||||||
RUN_TEST(test_a_repeater_edit_sends_the_repeaters);
|
RUN_TEST(test_a_repeater_edit_sends_the_repeaters);
|
||||||
RUN_TEST(test_deletes_send_nothing_more);
|
RUN_TEST(test_deletes_send_their_removal);
|
||||||
|
RUN_TEST(test_other_edits_remove_nothing);
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue