feat: command ops for socket protocol 2

shadeCommand, groupCommand, tiltCommand, repeatCommand, setPositions,
setSensor, setMyPosition, unpairShade, setRollingCode (types 16-24) are
read on async_tcp by ProtoOps and handed to loop() through the
LoopQueue, which replies once the request has run: ok, not found or
radio unavailable. A bad payload, a paused radio or a full queue is
answered straight away. sendRemoteCommand (25) touches nothing of the
shade model, so it goes to the radio from async_tcp like its route.

ShadeRequests::run() now says how a request went, not only whether
the radio took it. An op reads only the fields that were sent, so
setPositions can leave the tilt as it is. The shadeCommand event is
renamed shadeCommanded, since the op has the route's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-24 11:21:55 +02:00
parent 9fe05105ff
commit 0b54264ee3
18 changed files with 812 additions and 50 deletions

View file

@ -100,19 +100,19 @@ void tearDown() {}
/*********************************************************************
* Finding the shade or group
********************************************************************/
static void test_a_missing_shade_is_dropped() {
static void test_a_missing_shade_is_not_found() {
shade_request_t req = request(shade_request_type_t::shade_command);
req.target = 30;
TEST_ASSERT_TRUE(requests.run(req));
TEST_ASSERT_EQUAL(shade_request_result_t::not_found, requests.run(req));
TEST_ASSERT_EQUAL_STRING("", ops.calls.c_str());
}
static void test_a_missing_group_is_dropped() {
TEST_ASSERT_TRUE(requests.run(request(shade_request_type_t::group_command, 2)));
static void test_a_missing_group_is_not_found() {
TEST_ASSERT_EQUAL(shade_request_result_t::not_found, requests.run(request(shade_request_type_t::group_command, 2)));
TEST_ASSERT_EQUAL_STRING("", ops.calls.c_str());
}
static void test_a_shade_id_is_not_a_group_id() {
ops.shades[2] = rollerShade();
requests.run(request(shade_request_type_t::group_command, 2));
TEST_ASSERT_EQUAL(shade_request_result_t::not_found, requests.run(request(shade_request_type_t::group_command, 2)));
TEST_ASSERT_EQUAL_STRING("", ops.calls.c_str());
}
@ -179,7 +179,7 @@ static void test_set_positions_with_nothing_in_range_does_nothing() {
shade_request_t req = request(shade_request_type_t::set_positions);
req.position = -1;
req.tiltPosition = 101;
TEST_ASSERT_TRUE(requests.run(req));
TEST_ASSERT_EQUAL(shade_request_result_t::done, requests.run(req));
TEST_ASSERT_EQUAL_STRING("", ops.calls.c_str());
}
static void test_client_values_are_checked_on_the_way_in() {
@ -338,14 +338,14 @@ static void test_unpair_holds_prog_longer_on_a_56_bit_motor() {
static void test_unpair_the_radio_refused_leaves_the_shade_paired() {
ops.shades[4] = rollerShade();
ops.radioTakes = false;
TEST_ASSERT_FALSE(requests.run(request(shade_request_type_t::unpair)));
TEST_ASSERT_EQUAL(shade_request_result_t::radio_refused, requests.run(request(shade_request_type_t::unpair)));
TEST_ASSERT_EQUAL_STRING("sendCommand 4 Prog repeat=7 step=0", ops.calls.c_str());
}
static void test_rolling_code_is_set() {
ops.shades[4] = rollerShade();
shade_request_t req = request(shade_request_type_t::set_rolling_code);
req.rollingCode = 1234;
TEST_ASSERT_TRUE(requests.run(req));
TEST_ASSERT_EQUAL(shade_request_result_t::done, requests.run(req));
TEST_ASSERT_EQUAL_STRING("setRollingCode 4 1234", ops.calls.c_str());
}
@ -357,15 +357,15 @@ static void test_a_refused_command_is_reported() {
ops.radioTakes = false;
shade_request_t req = request(shade_request_type_t::shade_command);
req.target = 50;
TEST_ASSERT_FALSE(requests.run(req));
TEST_ASSERT_EQUAL(shade_request_result_t::radio_refused, requests.run(req));
}
int main(int argc, char **argv) {
(void)argc;
(void)argv;
UNITY_BEGIN();
RUN_TEST(test_a_missing_shade_is_dropped);
RUN_TEST(test_a_missing_group_is_dropped);
RUN_TEST(test_a_missing_shade_is_not_found);
RUN_TEST(test_a_missing_group_is_not_found);
RUN_TEST(test_a_shade_id_is_not_a_group_id);
RUN_TEST(test_target_moves_a_shade_there);
RUN_TEST(test_target_on_a_flipped_shade_is_turned_round);