Skip to content

Commit

Permalink
Expand rvc example app (project-chip#29159)
Browse files Browse the repository at this point in the history
* Added an RVC app example containg the RvcRunMode and RvcClean clusters.

* Regenerated zap code.

* Added the RvcRunMode and RvcClean clusters' logic to the RVC app example.

* Added the RvcOpState cluster's logic to the RVC app example.

* Added documentation about the RVC example app.

* Added an implementation for the GetCoutdownTime virtual function.

* Restyled by whitespace

* Restyled by clang-format

* Restyled by gn

* Added constants for the Cluster's endpoints. Adde vendor mode tags for the mapping mode.

* Restyled by clang-format

* Fixed the feature value for the RvcRun and RvcClean clusters.

* Restyled by clang-format

* zap regen after pull.

* Removed unused clusters form the zap and matter files.

* Modified the RvcRun ChangeToMode handler to fit the new state machine.

* RvcApp: Added a FIFO pipe for out-of-band messages.

* RVC App: Added all out-of-bound messages and their logic.

* OpState Server: Updated the documentation for the SetOperationalState method.

* RVC App: Update the RVC app state diagram.

* RVC App: Added PICS files for testing the RVC app.

* RVC App: Fixed state machine bug. Some invalid changes were being notified as being successful.

* RVC App: Fixed the PICS files to be accepted by the python test scripts.

* Added a readme to the RVC app example.

* Added an Error key to the ErrorEven out-of-band message to allow the user to trigger error state with all the availabele error state IDs.

* Configured the RvcOperationalState PICS to indicate that the device supports testing the device in all the different error states.

* Added a script to help test the RVC example app against all the yaml tests.

* Updated the readme to include information on how to run the yaml tests.

* Restyled by whitespace

* Restyled by clang-format

* Restyled by prettier-markdown

* Restyled by shellharden

* Restyled by shfmt

* RVC App: fixed spelling errors.

* RVC App: combined the PICS files into one file and updated the documentation.

* Typo fixes from code review.

Co-authored-by: Petru Lauric <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>

* Added missed error states that can be tested to the PICS files.

* removed non-applicable yaml tests.

* RVC App: Modified the readme to reduce the number of words that need to be added to the work list.

* Restyled by prettier-markdown

* RVC App: added the readme to the toc index.

* Restyled by prettier-markdown

* Fixed names of tests in helper script as some had been removed

* Updated yaml tests run script. Removed tests that did not apply.

* Readability

* Restyled by shfmt

---------

Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: Petru Lauric <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
Co-authored-by: Matthew Hazley <[email protected]>
  • Loading branch information
5 people authored Sep 13, 2023
1 parent 8edb9f0 commit 189967f
Show file tree
Hide file tree
Showing 17 changed files with 1,280 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1562,3 +1562,5 @@ zhengyaohan
Zigbee
zigbeealliance
zigbeethread
PIXIT
RVC
9 changes: 9 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,12 @@ window-app/**/README
resource-monitoring-app/**/README
```

## Air Quality Sensor example

```{toctree}
:glob:
:maxdepth: 1
rvc-app/README
```
125 changes: 125 additions & 0 deletions examples/rvc-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# RVC example app

This example app is meant to demonstrate an implementation of a Matter Robotic
Vacuum Cleaner device.

## State machine

Below is a diagram describing the state machine for this app.

![state machine](RVC_app_state_diagram.png)

This app can support most of the tests in the test plans.

## Out-of-band messages

Out-of-band messages are available to simulate typical device behaviors and
allow the app to navigate to all the states. To send an out-of-band message,
echo the JSON message to the `/tmp/chip_rvc_fifo_<PID>` file. The JSON message
must have a `"Name"` key that contains the command name. This name is shown in
the state machine diagram above. Example
`echo '{"Name": "Charged"}' > /tmp/chip_rvc_fifo_42`.

### `ErrorEvent` message

The error event message requires the additional key `"Error"` which specifies
the error state ID. This can be one of `UnableToStartOrResume`,
`UnableToCompleteOperation`, `CommandInvalidInState`,
`FailedToFindChargingDock`, `Stuck`, `DustBinMissing`, `DustBinFull`,
`WaterTankEmpty`, `WaterTankMissing`, `WaterTankLidOpen`,
`MopCleaningPadMissing`.

## Testing

A PICS file that details what this app supports testing is available in the
`pics` directory as a txt file. After building the RVC example app, chip-tool,
and setting up the testing environment, python tests can be executed with
`./scripts/tests/run_python_test.py --script src/python_testing/<script_name>.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg <PIXIT_Definitions:1>"`

**Note:** If the testing environment has not been commissioned with the RVC app,
use chip-tool to switch on the commissioning window
`chip-tool pairing open-commissioning-window`, and add the following flags to
the `--script-args` above.
`--commissioning-method on-network --discriminator XXXX --passcode XXXX`.

Below are the PIXIT definitions required for the different python tests.

### RVC Clean Mode cluster

#### TC 1.2

PIXIT: `PIXIT_ENDPOINT:1`
Example command:
`./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCCLEANM_1_2.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1"`

#### TC 2.1

PIXIT:
`PIXIT_ENDPOINT:1 PIXIT.RVCCLEANM.MODE_CHANGE_FAIL:1 PIXIT.RVCCLEANM.MODE_CHANGE_OK:2`
Example command:
`/scripts/tests/run_python_test.py --script src/python_testing/TC_RVCCLEANM_2_1.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1 PIXIT.RVCCLEANM.MODE_CHANGE_FAIL:1 PIXIT.RVCCLEANM.MODE_CHANGE_OK:2"`

When asked "Manually put the device in a state from which it will FAIL to
transition to mode 1", set the `RvcRunMode` to 1.
`chip-tool rvcrunmode change-to-mode 1`

When asked "Manually put the device in a state from which it will SUCCESSFULLY
transition to mode 2", set the `RvcRunMode` to 0.
`chip-tool rvcrunmode change-to-mode 0`

#### TC 3.2

This is not applicable because this RVC device does not support the
`StartUpMode` attribute.

### RVC Run Mode cluster

#### TC 1.2

PIXIT: `PIXIT_ENDPOINT:1` Example command:
`./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCRUNM_1_2.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1"`

#### TC 2.1

PIXIT:
`PIXIT_ENDPOINT:1 PIXIT.RVCRUNM.MODE_CHANGE_FAIL:2 PIXIT.RVCRUNM.MODE_CHANGE_OK:0`
Example command:
`./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCRUNM_2_1.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1 PIXIT.RVCRUNM.MODE_CHANGE_FAIL:2 PIXIT.RVCRUNM.MODE_CHANGE_OK:0"`

When asked "Manually put the device in a state from which it will FAIL to
transition to mode 2", set the `RvcRunMode` to 1.
`chip-tool rvcrunmode change-to-mode 1`

When asked "Manually put the device in a state from which it will SUCCESSFULLY
transition to mode 0", do nothing.

#### TC 3.2

This is not applicable because this RVC device does not support the
`StartUpMode` attribute.

### RVC Operational State cluster

#### TC 2.1

PIXIT: `PIXIT_ENDPOINT:1`
Example command:
`./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCOPSTATE_2_1.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1"`

Use the out-of-band messages, chip-tool messages and the state machine diagram
to navigate to the required states.

#### TC 2.3

PIXIT: `PIXIT_ENDPOINT:1`
Example command:
`./scripts/tests/run_python_test.py --script src/python_testing/TC_RVCOPSTATE_2_3.py --script-args "--storage-path admin_storage.json --PICS examples/rvc-app/rvc-common/pics/RVC_App_Test_Plan.txt --int-arg PIXIT_ENDPOINT:1"`

Use the out-of-band messages, chip-tool messages and the state machine diagram
to transition to the required states.

### Running the yaml tests

After commissioning the device, all the yaml tests can be run by running the
`run_all_yaml_tests.sh` script from the root dir with the node ID that the
device was commissioned with.
Binary file added examples/rvc-app/RVC_app_state_diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/rvc-app/RVC_app_state_diagram_drawio.xml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions examples/rvc-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ executable("chip-rvc-app") {
"${chip_root}/examples/rvc-app/rvc-common/src/rvc-device.cpp",
"${chip_root}/examples/rvc-app/rvc-common/src/rvc-mode-delegates.cpp",
"${chip_root}/examples/rvc-app/rvc-common/src/rvc-operational-state-delegate.cpp",
"RvcAppCommandDelegate.cpp",
"include/CHIPProjectAppConfig.h",
"main.cpp",
]
Expand All @@ -35,6 +36,7 @@ executable("chip-rvc-app") {
"${chip_root}/examples/platform/linux:app-main",
"${chip_root}/examples/rvc-app/rvc-common",
"${chip_root}/src/lib",
"${chip_root}/third_party/jsoncpp",
]

include_dirs = [
Expand Down
164 changes: 164 additions & 0 deletions examples/rvc-app/linux/RvcAppCommandDelegate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "RvcAppCommandDelegate.h"
#include <platform/PlatformManager.h>

#include "rvc-device.h"
#include <utility>

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

RvcAppCommandHandler * RvcAppCommandHandler::FromJSON(const char * json)
{
Json::Reader reader;
Json::Value value;

if (!reader.parse(json, value))
{
ChipLogError(NotSpecified, "RVC App: Error parsing JSON with error %s:", reader.getFormattedErrorMessages().c_str());
return nullptr;
}

if (value.empty() || !value.isObject())
{
ChipLogError(NotSpecified, "RVC App: Invalid JSON command received");
return nullptr;
}

if (!value.isMember("Name") || !value["Name"].isString())
{
ChipLogError(NotSpecified, "RVC App: Invalid JSON command received: command name is missing");
return nullptr;
}

return Platform::New<RvcAppCommandHandler>(std::move(value));
}

void RvcAppCommandHandler::HandleCommand(intptr_t context)
{
auto * self = reinterpret_cast<RvcAppCommandHandler *>(context);
std::string name = self->mJsonValue["Name"].asString();

VerifyOrExit(!self->mJsonValue.empty(), ChipLogError(NotSpecified, "Invalid JSON event command received"));

if (name == "Charged")
{
self->OnChargedHandler();
}
else if (name == "Charging")
{
self->OnChargingHandler();
}
else if (name == "Docked")
{
self->OnDockedHandler();
}
else if (name == "ChargerFound")
{
self->OnChargerFoundHandler();
}
else if (name == "LowCharge")
{
self->OnLowChargeHandler();
}
else if (name == "ActivityComplete")
{
self->OnActivityCompleteHandler();
}
else if (name == "ErrorEvent")
{
std::string error = self->mJsonValue["Error"].asString();
self->OnErrorEventHandler(error);
}
else if (name == "ClearError")
{
self->OnClearErrorHandler();
}
else
{
ChipLogError(NotSpecified, "Unhandled command: Should never happens");
}

exit:
Platform::Delete(self);
}

void RvcAppCommandHandler::SetRvcDevice(chip::app::Clusters::RvcDevice * aRvcDevice)
{
mRvcDevice = aRvcDevice;
}

void RvcAppCommandHandler::OnChargedHandler()
{
mRvcDevice->HandleChargedMessage();
}

void RvcAppCommandHandler::OnChargingHandler()
{
mRvcDevice->HandleChargingMessage();
}

void RvcAppCommandHandler::OnDockedHandler()
{
mRvcDevice->HandleDockedMessage();
}

void RvcAppCommandHandler::OnChargerFoundHandler()
{
mRvcDevice->HandleChargerFoundMessage();
}

void RvcAppCommandHandler::OnLowChargeHandler()
{
mRvcDevice->HandleLowChargeMessage();
}

void RvcAppCommandHandler::OnActivityCompleteHandler()
{
mRvcDevice->HandleActivityCompleteEvent();
}

void RvcAppCommandHandler::OnErrorEventHandler(const std::string & error)
{
mRvcDevice->HandleErrorEvent(error);
}

void RvcAppCommandHandler::OnClearErrorHandler()
{
mRvcDevice->HandleClearErrorMessage();
}

void RvcAppCommandDelegate::SetRvcDevice(chip::app::Clusters::RvcDevice * aRvcDevice)
{
mRvcDevice = aRvcDevice;
}

void RvcAppCommandDelegate::OnEventCommandReceived(const char * json)
{
auto handler = RvcAppCommandHandler::FromJSON(json);
if (nullptr == handler)
{
ChipLogError(NotSpecified, "RVC App: Unable to instantiate a command handler");
return;
}

handler->SetRvcDevice(mRvcDevice);
chip::DeviceLayer::PlatformMgr().ScheduleWork(RvcAppCommandHandler::HandleCommand, reinterpret_cast<intptr_t>(handler));
}
69 changes: 69 additions & 0 deletions examples/rvc-app/linux/RvcAppCommandDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "NamedPipeCommands.h"
#include "rvc-device.h"
#include <json/json.h>
#include <platform/DiagnosticDataProvider.h>

class RvcAppCommandHandler
{
public:
static RvcAppCommandHandler * FromJSON(const char * json);

static void HandleCommand(intptr_t context);

RvcAppCommandHandler(Json::Value && jasonValue) : mJsonValue(std::move(jasonValue)) {}

void SetRvcDevice(chip::app::Clusters::RvcDevice * aRvcDevice);

private:
Json::Value mJsonValue;
chip::app::Clusters::RvcDevice * mRvcDevice;

/**
* Should be called to notify that the device has finished charging.
*/
void OnChargedHandler();

void OnChargingHandler();

void OnDockedHandler();

void OnChargerFoundHandler();

void OnLowChargeHandler();

void OnActivityCompleteHandler();

void OnErrorEventHandler(const std::string & error);

void OnClearErrorHandler();
};

class RvcAppCommandDelegate : public NamedPipeCommandDelegate
{
private:
chip::app::Clusters::RvcDevice * mRvcDevice;

public:
void SetRvcDevice(chip::app::Clusters::RvcDevice * aRvcDevice);
void OnEventCommandReceived(const char * json) override;
};
Loading

0 comments on commit 189967f

Please sign in to comment.