Skip to content

Commit

Permalink
Implement startup behavior with StartUpMode (#16039)
Browse files Browse the repository at this point in the history
* Implement StartUpMode behavior with validation

* Disable TestModeSelectCluster for darwin. To be added back in #16514

* Update StartUpMode of ModeSelectCluster to use NVM storage option and generate code

* Restyled by clang-format

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
minhlez and restyled-commits authored Mar 24, 2022
1 parent a40104a commit d88beed
Show file tree
Hide file tree
Showing 29 changed files with 603 additions and 1,006 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1985,7 +1985,7 @@ server cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
attribute nullable int8u onMode = 5;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8033,7 +8033,7 @@
"reportableChange": 0
},
{
"name": "ServerGeneratedCommandList",
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
"side": "server",
Expand All @@ -8048,7 +8048,7 @@
"reportableChange": 0
},
{
"name": "ClientGeneratedCommandList",
"name": "AcceptedCommandList",
"code": 65529,
"mfgCode": null,
"side": "server",
Expand Down Expand Up @@ -8935,7 +8935,7 @@
"reportableChange": 0
},
{
"name": "ServerGeneratedCommandList",
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
"side": "server",
Expand All @@ -8950,7 +8950,7 @@
"reportableChange": 0
},
{
"name": "ClientGeneratedCommandList",
"name": "AcceptedCommandList",
"code": 65529,
"mfgCode": null,
"side": "server",
Expand Down Expand Up @@ -10531,7 +10531,7 @@
"mfgCode": null,
"side": "server",
"included": 1,
"storageOption": "RAM",
"storageOption": "NVM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0",
Expand Down Expand Up @@ -10571,7 +10571,7 @@
"reportableChange": 0
},
{
"name": "ServerGeneratedCommandList",
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
"side": "server",
Expand All @@ -10586,7 +10586,7 @@
"reportableChange": 0
},
{
"name": "ClientGeneratedCommandList",
"name": "AcceptedCommandList",
"code": 65529,
"mfgCode": null,
"side": "server",
Expand Down Expand Up @@ -14842,7 +14842,7 @@
"reportableChange": 0
},
{
"name": "ServerGeneratedCommandList",
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
"side": "server",
Expand All @@ -14857,7 +14857,7 @@
"reportableChange": 0
},
{
"name": "ClientGeneratedCommandList",
"name": "AcceptedCommandList",
"code": 65529,
"mfgCode": null,
"side": "server",
Expand Down
1 change: 0 additions & 1 deletion examples/chip-tool-darwin/templates/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ function getTests()
'TestIdentifyCluster',
'TestLogCommands',
'TestOperationalCredentialsCluster',
'TestModeSelectCluster',
'TestBinding',
];

Expand Down
4 changes: 2 additions & 2 deletions examples/placeholder/linux/apps/app1/config.matter
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ client cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
readonly global attribute attrib_id attributeList[] = 65531;
Expand Down Expand Up @@ -1053,7 +1053,7 @@ server cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
readonly global attribute attrib_id attributeList[] = 65531;
Expand Down
4 changes: 2 additions & 2 deletions examples/placeholder/linux/apps/app2/config.matter
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ client cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
readonly global attribute attrib_id attributeList[] = 65531;
Expand Down Expand Up @@ -1053,7 +1053,7 @@ server cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
readonly global attribute attrib_id attributeList[] = 65531;
Expand Down
114 changes: 114 additions & 0 deletions src/app/clusters/mode-select-server/mode-select-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,23 @@
#include <app/clusters/mode-select-server/supported-modes-manager.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/error-mapping.h>
#include <app/util/util.h>
#include <lib/support/CodeUtils.h>

using namespace std;
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ModeSelect;
using namespace chip::Protocols;

static InteractionModel::Status verifyModeValue(const EndpointId endpointId, const uint8_t newMode);

namespace {

inline bool areStartUpModeAndCurrentModeNonVolatile(EndpointId endpoint);

class ModeSelectAttrAccess : public AttributeAccessInterface
{
public:
Expand Down Expand Up @@ -103,7 +111,113 @@ bool emberAfModeSelectClusterChangeToModeCallback(CommandHandler * commandHandle
return true;
}

/**
* Callback for Mode Select Cluster Server Initialization.
* Enabled in src/app/zap-templates/templates/app/helper.js
* @param endpointId id of the endpoint that is being initialized
*/
void emberAfModeSelectClusterServerInitCallback(EndpointId endpointId)
{
// StartUp behavior relies on CurrentMode StartUpMode attributes being non-volatile.
if (areStartUpModeAndCurrentModeNonVolatile(endpointId))
{
// Read the StartUpMode attribute and set the CurrentMode attribute
// The StartUpMode attribute SHALL define the desired startup behavior of a
// device when it is supplied with power and this state SHALL be
// reflected in the CurrentMode attribute. The values of the StartUpMode
// attribute are listed below.

DataModel::Nullable<uint8_t> startUpMode;
EmberAfStatus status = Attributes::StartUpMode::Get(endpointId, startUpMode);
if (status == EMBER_ZCL_STATUS_SUCCESS && !startUpMode.IsNull())
{
// Initialise currentMode to 0
uint8_t currentMode = 0;
status = Attributes::CurrentMode::Get(endpointId, &currentMode);
if (status == EMBER_ZCL_STATUS_SUCCESS && startUpMode.Value() != currentMode)
{
status = Attributes::CurrentMode::Set(endpointId, startUpMode.Value());
if (status != EMBER_ZCL_STATUS_SUCCESS)
{
ChipLogError(Zcl, "ModeSelect: Error initializing CurrentMode, EmberAfStatus code 0x%02x", status);
}
else
{
emberAfPrintln(EMBER_AF_PRINT_DEBUG, "ModeSelect: Successfully initialized CurrentMode to %u",
startUpMode.Value());
}
}
}
}
else
{
emberAfPrintln(EMBER_AF_PRINT_DEBUG,
"ModeSelect: Skipped initializing CurrentMode by StartUpMode because one of them is volatile");
}
}

namespace {

/**
* Checks if StartUpMode and CurrentMode are non-volatile.
* @param endpointId id of the endpoint to check
* @return true if both attributes are non-volatile; false otherwise.
*/
inline bool areStartUpModeAndCurrentModeNonVolatile(EndpointId endpointId)
{
return emberAfIsNonVolatileAttribute(endpointId, ModeSelect::Id, Attributes::CurrentMode::Id, true) &&
emberAfIsNonVolatileAttribute(endpointId, ModeSelect::Id, Attributes::StartUpMode::Id, true);
}

} // namespace

void MatterModeSelectPluginServerInitCallback(void)
{
registerAttributeAccessOverride(&gModeSelectAttrAccess);
}

/**
* Callback for Mode Select Cluster Server Pre Attribute Changed
* Enabled in src/app/zap-templates/templates/app/helper.js
* @param attributePath Concrete attribute path to be changed
* @param attributeType Attribute type
* @param size Attribute size
* @param value Attribute value
*/
InteractionModel::Status MatterModeSelectClusterServerPreAttributeChangedCallback(const ConcreteAttributePath & attributePath,
EmberAfAttributeType attributeType, uint16_t size,
uint8_t * value)
{
const EndpointId endpointId = attributePath.mEndpointId;
InteractionModel::Status result;

switch (attributePath.mAttributeId)
{
case ModeSelect::Attributes::StartUpMode::Id:
result = verifyModeValue(endpointId, *value);
break;
default:
result = InteractionModel::Status::Success;
}

return result;
}

/**
* Checks the new mode against the endpoint's supported modes.
* @param endpointId endpointId of the endpoint
* @param newMode value of the new mode
* @return Success status if the value is valid; InvalidValue otherwise.
*/
static InteractionModel::Status verifyModeValue(const EndpointId endpointId, const uint8_t newMode)
{
const ModeSelect::Structs::ModeOptionStruct::Type * modeOptionPtr;
EmberAfStatus checkSupportedModeStatus =
ModeSelect::getSupportedModesManager()->getModeOptionByMode(endpointId, newMode, &modeOptionPtr);
if (EMBER_ZCL_STATUS_SUCCESS != checkSupportedModeStatus)
{
const InteractionModel::Status returnStatus = ToInteractionModelStatus(checkSupportedModeStatus);
return returnStatus;
}
return InteractionModel::Status::Success;
}
52 changes: 52 additions & 0 deletions src/app/tests/suites/TestModeSelectCluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ config:
nodeId: 0x12344321
cluster: "Mode Select"
endpoint: 1
discriminator:
type: INT16U
defaultValue: 3840

tests:
- label: "Wait for the commissioned device to be retrieved"
Expand Down Expand Up @@ -135,3 +138,52 @@ tests:
attribute: "CurrentMode"
response:
value: OnModeValue

- label: "Change to Unsupported StartUp Mode"
command: "writeAttribute"
attribute: "StartUpMode"
arguments:
value: 2
response:
error: CONSTRAINT_ERROR

- label: "Change to Supported StartUp Mode"
command: "writeAttribute"
attribute: "StartUpMode"
arguments:
value: 7

- label: "Verify StartUp Mode Change"
command: "readAttribute"
attribute: "StartUpMode"
response:
value: 7

- label: "Change CurrentMode to another value"
command: "changeToMode"
arguments:
values:
- name: "NewMode"
value: 0

- label: "Reboot target device"
cluster: "SystemCommands"
command: "Reboot"
arguments:
values:
- name: "discriminator"
value: discriminator

- label: "Wait for the commissioned device to be retrieved"
cluster: "DelayCommands"
command: "WaitForCommissionee"
arguments:
values:
- name: "nodeId"
value: nodeId

- label: "Verify Current Mode Change based on new StartUp Mode"
command: "readAttribute"
attribute: "CurrentMode"
response:
value: 7
8 changes: 7 additions & 1 deletion src/app/zap-templates/templates/app/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ var endpointClusterWithInit = [
'Scenes',
'Time Format Localization',
'Thermostat',
'Mode Select',
];
var endpointClusterWithAttributeChanged = [
'Bridged Device Basic',
Expand All @@ -129,7 +130,12 @@ var endpointClusterWithAttributeChanged = [
'Window Covering',
];
var endpointClusterWithPreAttribute = [
'IAS Zone', 'Door Lock', 'Thermostat User Interface Configuration', 'Time Format Localization', 'Localization Configuration'
'IAS Zone',
'Door Lock',
'Thermostat User Interface Configuration',
'Time Format Localization',
'Localization Configuration',
'Mode Select',
];
var endpointClusterWithMessageSent = [ 'IAS Zone' ];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ limitations under the License.
<attribute side="server" code="0x0001" define="STANDARD_NAMESPACE" type="ENUM16" writable="false" optional="false" isNullable="true">StandardNamespace</attribute>
<attribute side="server" code="0x0002" define="SUPPORTED_MODES" type="ARRAY" entryType="ModeOptionStruct" writable="false" optional="false" isNullable="false">SupportedModes</attribute>
<attribute side="server" code="0x0003" define="CURRENT_MODE" type="INT8U" writable="false" optional="false" isNullable="false" reportable="true">CurrentMode</attribute>
<attribute side="server" code="0x0004" define="START_UP_MODE" type="INT8U" writable="false" optional="true" isNullable="true">StartUpMode</attribute>
<attribute side="server" code="0x0004" define="START_UP_MODE" type="INT8U" writable="true" optional="true" isNullable="true">StartUpMode</attribute>
<attribute side="server" code="0x0005" define="ON_MODE" type="INT8U" writable="true" optional="true" isNullable="true">OnMode</attribute>

<!-- Test Commands -->
Expand Down
2 changes: 1 addition & 1 deletion src/controller/data_model/controller-clusters.matter
Original file line number Diff line number Diff line change
Expand Up @@ -2380,7 +2380,7 @@ client cluster ModeSelect = 80 {
readonly attribute nullable enum16 standardNamespace = 1;
readonly attribute ModeOptionStruct supportedModes[] = 2;
readonly attribute int8u currentMode = 3;
readonly attribute nullable int8u startUpMode = 4;
attribute nullable int8u startUpMode = 4;
attribute nullable int8u onMode = 5;
readonly global attribute command_id generatedCommandList[] = 65528;
readonly global attribute command_id acceptedCommandList[] = 65529;
Expand Down
Loading

0 comments on commit d88beed

Please sign in to comment.