Skip to content

Commit

Permalink
Implement TC-SWTCH-2.4 and all-clusters button simulator (project-chi…
Browse files Browse the repository at this point in the history
…p#34406)

* Implement TC-SWTCH-2.4 and all-clusters button simulator

- Implement TC-SWTCH-2.4
- Implement action switch button simulator to drive the test

Testing done:

- New test (TC-SWTCH-2.4) works using the button simulator

* Restyled by clang-format

* Restyled by autopep8

* Restyled by isort

* Enable TC_SWTCH.py in CI

* Fix lint

* Fix typo that arose on file saving

* Handle EOF in reading user input in matter testing support

* Do not provide a stdin on python test runner and handle EOF on matter_testing_support

* Fix up PICS execution for CI

---------

Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: Andrei Litvin <[email protected]>
  • Loading branch information
3 people authored and j-ororke committed Jul 31, 2024
1 parent 71e63ff commit d38e946
Show file tree
Hide file tree
Showing 8 changed files with 865 additions and 13 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ jobs:
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_3.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_RVCOPSTATE_2_4.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_SC_7_1.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --load-from-env /tmp/test_env.yaml --script src/python_testing/TC_SWTCH.py'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestConformanceSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestMatterTestingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
scripts/run_in_python_env.sh out/venv './scripts/tests/run_python_test.py --script "src/python_testing/TestSpecParsingSupport.py" --script-args "--trace-to json:out/trace_data/test-{SCRIPT_BASE_NAME}.json --trace-to perfetto:out/trace_data/test-{SCRIPT_BASE_NAME}.perfetto"'
Expand Down
151 changes: 151 additions & 0 deletions examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <app/util/attribute-storage.h>
#include <platform/PlatformManager.h>

#include "ButtonEventsSimulator.h"
#include <air-quality-instance.h>
#include <dishwasher-mode.h>
#include <laundry-washer-mode.h>
Expand All @@ -36,13 +37,155 @@
#include <oven-operational-state-delegate.h>
#include <rvc-modes.h>

#include <memory>
#include <string>
#include <utility>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::DeviceLayer;

namespace {

std::unique_ptr<ButtonEventsSimulator> sButtonSimulatorInstance{ nullptr };

bool HasNumericField(Json::Value & jsonValue, const std::string & field)
{
return jsonValue.isMember(field) && jsonValue[field].isNumeric();
}

/**
* Named pipe handler for simulated long press on an action switch.
*
* Usage example:
* echo '{"Name": "SimulateActionSwitchLongPress", "EndpointId": 3, "ButtonId": 1, "LongPressDelayMillis": 800,
* "LongPressDurationMillis": 1000}' > /tmp/chip_all_clusters_fifo_1146610
*
* JSON Arguments:
* - "Name": Must be "SimulateActionSwitchLongPress"
* - "EndpointId": number of endpoint having a switch cluster
* - "ButtonId": switch position in the switch cluster for "down" button (not idle)
* - "LongPressDelayMillis": Time in milliseconds before the LongPress
* - "LongPressDurationMillis": Total duration in milliseconds from start of the press to LongRelease
*
* @param jsonValue - JSON payload from named pipe
*/
void HandleSimulateActionSwitchLongPress(Json::Value & jsonValue)
{
if (sButtonSimulatorInstance != nullptr)
{
ChipLogError(NotSpecified, "Button simulation already in progress! Ignoring request.");
return;
}

bool hasEndpointId = HasNumericField(jsonValue, "EndpointId");
bool hasButtonId = HasNumericField(jsonValue, "ButtonId");
bool hasLongPressDelayMillis = HasNumericField(jsonValue, "LongPressDelayMillis");
bool hasLongPressDurationMillis = HasNumericField(jsonValue, "LongPressDurationMillis");
if (!hasEndpointId || !hasButtonId || !hasLongPressDelayMillis || !hasLongPressDurationMillis)
{
std::string inputJson = jsonValue.toStyledString();
ChipLogError(
NotSpecified,
"Missing or invalid value for one of EndpointId, ButtonId, LongPressDelayMillis or LongPressDurationMillis in %s",
inputJson.c_str());
return;
}

EndpointId endpointId = static_cast<EndpointId>(jsonValue["EndpointId"].asUInt());
uint8_t buttonId = static_cast<uint8_t>(jsonValue["ButtonId"].asUInt());
System::Clock::Milliseconds32 longPressDelayMillis{ static_cast<unsigned>(jsonValue["LongPressDelayMillis"].asUInt()) };
System::Clock::Milliseconds32 longPressDurationMillis{ static_cast<unsigned>(jsonValue["LongPressDurationMillis"].asUInt()) };
auto buttonSimulator = std::make_unique<ButtonEventsSimulator>();

bool success = buttonSimulator->SetMode(ButtonEventsSimulator::Mode::kModeLongPress)
.SetLongPressDelayMillis(longPressDelayMillis)
.SetLongPressDurationMillis(longPressDurationMillis)
.SetIdleButtonId(0)
.SetPressedButtonId(buttonId)
.SetEndpointId(endpointId)
.Execute([]() { sButtonSimulatorInstance.reset(); });

if (!success)
{
ChipLogError(NotSpecified, "Failed to start execution of button simulator!");
return;
}

sButtonSimulatorInstance = std::move(buttonSimulator);
}

/**
* Named pipe handler for simulated multi-press on an action switch.
*
* Usage example:
* echo '{"Name": "SimulateActionSwitchMultiPress", "EndpointId": 3, "ButtonId": 1, "MultiPressPressedTimeMillis": 100,
* "MultiPressReleasedTimeMillis": 350, "MultiPressNumPresses": 2}' > /tmp/chip_all_clusters_fifo_1146610
*
* JSON Arguments:
* - "Name": Must be "SimulateActionSwitchMultiPress"
* - "EndpointId": number of endpoint having a switch cluster
* - "ButtonId": switch position in the switch cluster for "down" button (not idle)
* - "MultiPressPressedTimeMillis": Pressed time in milliseconds for each press
* - "MultiPressReleasedTimeMillis": Released time in milliseconds after each press
* - "MultiPressNumPresses": Number of presses to simulate
*
* @param jsonValue - JSON payload from named pipe
*/
void HandleSimulateActionSwitchMultiPress(Json::Value & jsonValue)
{
if (sButtonSimulatorInstance != nullptr)
{
ChipLogError(NotSpecified, "Button simulation already in progress! Ignoring request.");
return;
}

bool hasEndpointId = HasNumericField(jsonValue, "EndpointId");
bool hasButtonId = HasNumericField(jsonValue, "ButtonId");
bool hasMultiPressPressedTimeMillis = HasNumericField(jsonValue, "MultiPressPressedTimeMillis");
bool hasMultiPressReleasedTimeMillis = HasNumericField(jsonValue, "MultiPressReleasedTimeMillis");
bool hasMultiPressNumPresses = HasNumericField(jsonValue, "MultiPressNumPresses");
if (!hasEndpointId || !hasButtonId || !hasMultiPressPressedTimeMillis || !hasMultiPressReleasedTimeMillis ||
!hasMultiPressNumPresses)
{
std::string inputJson = jsonValue.toStyledString();
ChipLogError(NotSpecified,
"Missing or invalid value for one of EndpointId, ButtonId, MultiPressPressedTimeMillis, "
"MultiPressReleasedTimeMillis or MultiPressNumPresses in %s",
inputJson.c_str());
return;
}

EndpointId endpointId = static_cast<EndpointId>(jsonValue["EndpointId"].asUInt());
uint8_t buttonId = static_cast<uint8_t>(jsonValue["ButtonId"].asUInt());
System::Clock::Milliseconds32 multiPressPressedTimeMillis{ static_cast<unsigned>(
jsonValue["MultiPressPressedTimeMillis"].asUInt()) };
System::Clock::Milliseconds32 multiPressReleasedTimeMillis{ static_cast<unsigned>(
jsonValue["MultiPressReleasedTimeMillis"].asUInt()) };
uint8_t multiPressNumPresses = static_cast<uint8_t>(jsonValue["MultiPressNumPresses"].asUInt());
auto buttonSimulator = std::make_unique<ButtonEventsSimulator>();

bool success = buttonSimulator->SetMode(ButtonEventsSimulator::Mode::kModeMultiPress)
.SetMultiPressPressedTimeMillis(multiPressPressedTimeMillis)
.SetMultiPressReleasedTimeMillis(multiPressReleasedTimeMillis)
.SetMultiPressNumPresses(multiPressNumPresses)
.SetIdleButtonId(0)
.SetPressedButtonId(buttonId)
.SetEndpointId(endpointId)
.Execute([]() { sButtonSimulatorInstance.reset(); });

if (!success)
{
ChipLogError(NotSpecified, "Failed to start execution of button simulator!");
return;
}

sButtonSimulatorInstance = std::move(buttonSimulator);
}

} // namespace

AllClustersAppCommandHandler * AllClustersAppCommandHandler::FromJSON(const char * json)
{
Json::Reader reader;
Expand Down Expand Up @@ -190,6 +333,14 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context)
std::string operation = self->mJsonValue["Operation"].asString();
self->OnOperationalStateChange(device, operation, self->mJsonValue["Param"]);
}
else if (name == "SimulateActionSwitchLongPress")
{
HandleSimulateActionSwitchLongPress(self->mJsonValue);
}
else if (name == "SimulateActionSwitchMultiPress")
{
HandleSimulateActionSwitchMultiPress(self->mJsonValue);
}
else
{
ChipLogError(NotSpecified, "Unhandled command: Should never happens");
Expand Down
3 changes: 3 additions & 0 deletions examples/all-clusters-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ source_set("chip-all-clusters-common") {
"${chip_root}/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp",
"AllClustersCommandDelegate.cpp",
"AllClustersCommandDelegate.h",
"AppOptions.cpp",
"ButtonEventsSimulator.cpp",
"ButtonEventsSimulator.h",
"ValveControlDelegate.cpp",
"WindowCoveringManager.cpp",
"include/tv-callbacks.cpp",
Expand Down
Loading

0 comments on commit d38e946

Please sign in to comment.