Skip to content

Commit 197d02b

Browse files
committedAug 2, 2024·
Implement DM::Provider::Write usage
1 parent 26c816a commit 197d02b

19 files changed

+360
-41
lines changed
 

‎scripts/build/build/targets.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,9 @@ def BuildHostTarget():
110110
TargetPart('all-clusters-minimal', app=HostApp.ALL_CLUSTERS_MINIMAL),
111111
TargetPart('chip-tool', app=HostApp.CHIP_TOOL),
112112
TargetPart('thermostat', app=HostApp.THERMOSTAT),
113-
TargetPart('java-matter-controller',
114-
app=HostApp.JAVA_MATTER_CONTROLLER),
115-
TargetPart('kotlin-matter-controller',
116-
app=HostApp.KOTLIN_MATTER_CONTROLLER),
113+
# TODO: controllers depending on a datamodel is odd. For now fix compile dependencies on ember.
114+
TargetPart('java-matter-controller', app=HostApp.JAVA_MATTER_CONTROLLER, chip_use_data_model="disabled"),
115+
TargetPart('kotlin-matter-controller', app=HostApp.KOTLIN_MATTER_CONTROLLER, chip_use_data_model="disabled"),
117116
TargetPart('minmdns', app=HostApp.MIN_MDNS),
118117
TargetPart('light', app=HostApp.LIGHT),
119118
TargetPart('lock', app=HostApp.LOCK),
@@ -189,6 +188,9 @@ def BuildHostTarget():
189188
target.AppendModifier('enable-dnssd-tests', enable_dnssd_tests=True).OnlyIfRe('-tests')
190189
target.AppendModifier('disable-dnssd-tests', enable_dnssd_tests=False).OnlyIfRe('-tests')
191190
target.AppendModifier('chip-casting-simplified', chip_casting_simplified=True).OnlyIfRe('-tv-casting-app')
191+
target.AppendModifier('data-model-check', data_model_interface="check").ExceptIfRe('-data-model-(enabled|disabled)')
192+
target.AppendModifier('data-model-disabled', data_model_interface="disabled").ExceptIfRe('-data-model-(check|enabled)')
193+
target.AppendModifier('data-model-enabled', data_model_interface="enabled").ExceptIfRe('-data-model-(check|disabled)')
192194

193195
return target
194196

‎scripts/build/builders/host.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE,
317317
minmdns_high_verbosity=False, imgui_ui=False, crypto_library: HostCryptoLibrary = None,
318318
enable_test_event_triggers=None,
319319
enable_dnssd_tests: Optional[bool] = None,
320-
chip_casting_simplified: Optional[bool] = None
320+
chip_casting_simplified: Optional[bool] = None,
321+
data_model_interface: Optional[bool] = None,
321322
):
322323
super(HostBuilder, self).__init__(
323324
root=os.path.join(root, 'examples', app.ExamplePath()),
@@ -352,6 +353,9 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE,
352353
if use_ubsan:
353354
self.extra_gn_options.append('is_ubsan=true')
354355

356+
if data_model_interface is not None:
357+
self.extra_gn_options.append(f'chip_use_data_model_interface="{data_model_interface}"')
358+
355359
if use_dmalloc:
356360
self.extra_gn_options.append('chip_config_memory_debug_checks=true')
357361
self.extra_gn_options.append('chip_config_memory_debug_dmalloc=true')
@@ -457,10 +461,6 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE,
457461
if self.app == HostApp.SIMULATED_APP2:
458462
self.extra_gn_options.append('chip_tests_zap_config="app2"')
459463

460-
if self.app in {HostApp.JAVA_MATTER_CONTROLLER, HostApp.KOTLIN_MATTER_CONTROLLER}:
461-
# TODO: controllers depending on a datamodel is odd. For now fix compile dependencies on ember.
462-
self.extra_gn_options.append('chip_use_data_model_interface="disabled"')
463-
464464
if self.app == HostApp.TESTS and fuzzing_type != HostFuzzingType.NONE:
465465
self.build_command = 'fuzz_tests'
466466

‎scripts/build/testdata/all_targets_linux_x64.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ efr32-{brd2704b,brd4316a,brd4317a,brd4318a,brd4319a,brd4186a,brd4187a,brd2601b,b
99
esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,energy-management,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only][-tracing]
1010
genio-lighting-app
1111
linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang]
12-
linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified]
12+
linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,kotlin-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,simulated-app1,simulated-app2,python-bindings,tv-app,tv-casting-app,bridge,fabric-admin,fabric-bridge,tests,chip-cert,address-resolve-tool,contact-sensor,dishwasher,microwave-oven,refrigerator,rvc,air-purifier,lit-icd,air-quality-sensor,network-manager,energy-management}[-nodeps][-nlfaultinject][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui][-evse-test-event][-enable-dnssd-tests][-disable-dnssd-tests][-chip-casting-simplified][-data-model-check][-data-model-disabled][-data-model-enabled]
1313
linux-x64-efr32-test-runner[-clang]
1414
imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release]
1515
infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage][-trustm]

‎src/app/AttributeValueDecoder.h

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class AttributeValueDecoder
6565
const Access::SubjectDescriptor & GetSubjectDescriptor() const { return mSubjectDescriptor; }
6666

6767
private:
68+
friend class TestOnlyAttributeValueDecoderAccessor;
69+
6870
TLV::TLVReader & mReader;
6971
bool mTriedDecode = false;
7072
const Access::SubjectDescriptor mSubjectDescriptor;

‎src/app/EventManagement.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,12 @@ void EventManagement::SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t
850850
aInitialWrittenEventBytes = mBytesWritten;
851851
}
852852

853+
CHIP_ERROR EventManagement::GenerateEvent(EventLoggingDelegate * eventPayloadWriter, const EventOptions & options,
854+
EventNumber & generatedEventNumber)
855+
{
856+
return LogEvent(eventPayloadWriter, options, generatedEventNumber);
857+
}
858+
853859
void CircularEventBuffer::Init(uint8_t * apBuffer, uint32_t aBufferLength, CircularEventBuffer * apPrev,
854860
CircularEventBuffer * apNext, PriorityLevel aPriorityLevel)
855861
{
@@ -909,5 +915,6 @@ CHIP_ERROR CircularEventBufferWrapper::GetNextBuffer(TLVReader & aReader, const
909915
exit:
910916
return err;
911917
}
918+
912919
} // namespace app
913920
} // namespace chip

‎src/app/EventManagement.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <app/EventLoggingTypes.h>
3232
#include <app/MessageDef/EventDataIB.h>
3333
#include <app/MessageDef/StatusIB.h>
34+
#include <app/data-model-provider/EventsGenerator.h>
3435
#include <app/util/basic-types.h>
3536
#include <lib/core/TLVCircularBuffer.h>
3637
#include <lib/support/CHIPCounter.h>
@@ -196,7 +197,7 @@ struct LogStorageResources
196197
* more space for new events.
197198
*/
198199

199-
class EventManagement
200+
class EventManagement : public DataModel::EventsGenerator
200201
{
201202
public:
202203
/**
@@ -387,6 +388,10 @@ class EventManagement
387388
*/
388389
void SetScheduledEventInfo(EventNumber & aEventNumber, uint32_t & aInitialWrittenEventBytes) const;
389390

391+
/* EventsGenerator implementation */
392+
CHIP_ERROR GenerateEvent(EventLoggingDelegate * eventPayloadWriter, const EventOptions & options,
393+
EventNumber & generatedEventNumber) override;
394+
390395
private:
391396
/**
392397
* @brief
@@ -559,5 +564,6 @@ class EventManagement
559564

560565
System::Clock::Milliseconds64 mMonotonicStartupTime;
561566
};
567+
562568
} // namespace app
563569
} // namespace chip

‎src/app/InteractionModelEngine.cpp

+38-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525

2626
#include "InteractionModelEngine.h"
27+
#include "lib/core/CHIPError.h"
2728

2829
#include <cinttypes>
2930

@@ -873,7 +874,7 @@ Protocols::InteractionModel::Status InteractionModelEngine::OnWriteRequest(Messa
873874
{
874875
if (writeHandler.IsFree())
875876
{
876-
VerifyOrReturnError(writeHandler.Init(this) == CHIP_NO_ERROR, Status::Busy);
877+
VerifyOrReturnError(writeHandler.Init(GetDataModelProvider(), this) == CHIP_NO_ERROR, Status::Busy);
877878
return writeHandler.OnWriteRequest(apExchangeContext, std::move(aPayload), aIsTimedWrite);
878879
}
879880
}
@@ -974,6 +975,10 @@ CHIP_ERROR InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext
974975

975976
Protocols::InteractionModel::Status status = Status::Failure;
976977

978+
// Ensure that DataModel::Provider have access to the currently executing
979+
// exchange context.
980+
ScopedExchangeContext scopedExchangeContext(*this, apExchangeContext);
981+
977982
// Group Message can only be an InvokeCommandRequest or WriteRequest
978983
if (apExchangeContext->IsGroupExchangeContext() &&
979984
!aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandRequest) &&
@@ -1711,16 +1716,43 @@ DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Pr
17111716
// Alternting data model should not be done while IM is actively handling requests.
17121717
VerifyOrDie(mReadHandlers.begin() == mReadHandlers.end());
17131718

1714-
DataModel::Provider * oldModel = GetDataModelProvider();
1715-
mDataModelProvider = model;
1719+
DataModel::Provider * oldModel = mDataModelProvider;
1720+
if (oldModel != nullptr)
1721+
{
1722+
CHIP_ERROR err = oldModel->Shutdown();
1723+
if (err != CHIP_NO_ERROR)
1724+
{
1725+
ChipLogError(InteractionModel, "Failure on interaction model shutdown: %" CHIP_ERROR_FORMAT, err.Format());
1726+
}
1727+
}
1728+
1729+
mDataModelProvider = model;
1730+
if (mDataModelProvider != nullptr)
1731+
{
1732+
DataModel::InteractionModelContext context;
1733+
1734+
context.eventsGenerator = &EventManagement::GetInstance();
1735+
context.dataModelChangeListener = &mReportingEngine;
1736+
context.actionContext = this;
1737+
1738+
CHIP_ERROR err = mDataModelProvider->Startup(context);
1739+
if (err != CHIP_NO_ERROR)
1740+
{
1741+
ChipLogError(InteractionModel, "Failure on interaction model startup: %" CHIP_ERROR_FORMAT, err.Format());
1742+
}
1743+
}
1744+
17161745
return oldModel;
17171746
}
17181747

1719-
DataModel::Provider * InteractionModelEngine::GetDataModelProvider() const
1748+
DataModel::Provider * InteractionModelEngine::GetDataModelProvider()
17201749
{
17211750
#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
1722-
// TODO: this should be temporary, we should fully inject the data model
1723-
VerifyOrReturnValue(mDataModelProvider != nullptr, CodegenDataModelProviderInstance());
1751+
if (mDataModelProvider == nullptr)
1752+
{
1753+
// Generally this is expected to be thread safe as these should be called within the CHIP processing loop.
1754+
SetDataModelProvider(CodegenDataModelProviderInstance());
1755+
}
17241756
#endif
17251757
return mDataModelProvider;
17261758
}

‎src/app/InteractionModelEngine.h

+25-2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ namespace app {
8686
*/
8787
class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
8888
public Messaging::ExchangeDelegate,
89+
public DataModel::ActionContext,
8990
public CommandResponseSender::Callback,
9091
public CommandHandlerImpl::Callback,
9192
public ReadHandler::ManagementCallback,
@@ -402,7 +403,10 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
402403
}
403404
#endif
404405

405-
DataModel::Provider * GetDataModelProvider() const;
406+
// Temporarly NOT const because the data model provider will be auto-set
407+
// to codegen on first usage. This behaviour will be changed once each
408+
// application must explicitly set the data model provider.
409+
DataModel::Provider * GetDataModelProvider();
406410

407411
// MUST NOT be used while the interaction model engine is running as interaction
408412
// model functionality (e.g. active reads/writes/subscriptions) rely on data model
@@ -411,6 +415,9 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
411415
// Returns the old data model provider value.
412416
DataModel::Provider * SetDataModelProvider(DataModel::Provider * model);
413417

418+
/* DataModel::ActionContext implementation */
419+
Messaging::ExchangeContext * CurrentExchange() override { return mCurrentExchange; }
420+
414421
private:
415422
friend class reporting::Engine;
416423
friend class TestCommandInteraction;
@@ -698,7 +705,23 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler,
698705

699706
SubscriptionResumptionStorage * mpSubscriptionResumptionStorage = nullptr;
700707

701-
DataModel::Provider * mDataModelProvider = nullptr;
708+
DataModel::Provider * mDataModelProvider = nullptr;
709+
Messaging::ExchangeContext * mCurrentExchange = nullptr;
710+
711+
// Changes the current exchange context of a InteractionModelEngine to a given context
712+
class ScopedExchangeContext
713+
{
714+
public:
715+
ScopedExchangeContext(InteractionModelEngine & engine, Messaging::ExchangeContext * context) : mEngine(engine)
716+
{
717+
mEngine.mCurrentExchange = context;
718+
}
719+
720+
~ScopedExchangeContext() { mEngine.mCurrentExchange = nullptr; }
721+
722+
private:
723+
InteractionModelEngine & mEngine;
724+
};
702725
};
703726

704727
} // namespace app

‎src/app/WriteHandler.cpp

+40-6
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,23 @@
1616
* limitations under the License.
1717
*/
1818

19-
#include "messaging/ExchangeContext.h"
2019
#include <app/AppConfig.h>
2120
#include <app/AttributeAccessInterfaceRegistry.h>
21+
#include <app/AttributeValueDecoder.h>
2222
#include <app/InteractionModelEngine.h>
2323
#include <app/MessageDef/EventPathIB.h>
2424
#include <app/MessageDef/StatusIB.h>
2525
#include <app/StatusResponse.h>
2626
#include <app/WriteHandler.h>
27+
#include <app/data-model-provider/OperationTypes.h>
2728
#include <app/reporting/Engine.h>
2829
#include <app/util/MatterCallbacks.h>
2930
#include <app/util/ember-compatibility-functions.h>
3031
#include <credentials/GroupDataProvider.h>
32+
#include <lib/core/CHIPError.h>
33+
#include <lib/support/CodeUtils.h>
3134
#include <lib/support/TypeTraits.h>
35+
#include <messaging/ExchangeContext.h>
3236
#include <protocols/interaction_model/StatusCode.h>
3337

3438
namespace chip {
@@ -38,10 +42,14 @@ using namespace Protocols::InteractionModel;
3842
using Status = Protocols::InteractionModel::Status;
3943
constexpr uint8_t kListAttributeType = 0x48;
4044

41-
CHIP_ERROR WriteHandler::Init(WriteHandlerDelegate * apWriteHandlerDelegate)
45+
CHIP_ERROR WriteHandler::Init(DataModel::Provider * apProvider, WriteHandlerDelegate * apWriteHandlerDelegate)
4246
{
4347
VerifyOrReturnError(!mExchangeCtx, CHIP_ERROR_INCORRECT_STATE);
4448
VerifyOrReturnError(apWriteHandlerDelegate, CHIP_ERROR_INVALID_ARGUMENT);
49+
#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
50+
VerifyOrReturnError(apProvider, CHIP_ERROR_INVALID_ARGUMENT);
51+
mDataModelProvider = apProvider;
52+
#endif
4553

4654
mDelegate = apWriteHandlerDelegate;
4755
MoveToState(State::Initialized);
@@ -63,6 +71,9 @@ void WriteHandler::Close()
6371
DeliverFinalListWriteEnd(false /* wasSuccessful */);
6472
mExchangeCtx.Release();
6573
mSuppressResponse = false;
74+
#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
75+
mDataModelProvider = nullptr;
76+
#endif
6677
MoveToState(State::Uninitialized);
6778
}
6879

@@ -351,7 +362,7 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData
351362
err = CHIP_NO_ERROR;
352363
}
353364
SuccessOrExit(err);
354-
err = WriteSingleClusterData(subjectDescriptor, dataAttributePath, dataReader, this);
365+
err = WriteClusterData(subjectDescriptor, dataAttributePath, dataReader);
355366
if (err != CHIP_NO_ERROR)
356367
{
357368
mWriteResponseBuilder.GetWriteResponses().Rollback(backup);
@@ -497,12 +508,11 @@ CHIP_ERROR WriteHandler::ProcessGroupAttributeDataIBs(TLV::TLVReader & aAttribut
497508

498509
DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Write,
499510
DataModelCallbacks::OperationOrder::Pre, dataAttributePath);
500-
err = WriteSingleClusterData(subjectDescriptor, dataAttributePath, tmpDataReader, this);
501-
511+
err = WriteClusterData(subjectDescriptor, dataAttributePath, tmpDataReader);
502512
if (err != CHIP_NO_ERROR)
503513
{
504514
ChipLogError(DataManagement,
505-
"WriteSingleClusterData Endpoint=%u Cluster=" ChipLogFormatMEI " Attribute =" ChipLogFormatMEI
515+
"WriteClusterData Endpoint=%u Cluster=" ChipLogFormatMEI " Attribute =" ChipLogFormatMEI
506516
" failed: %" CHIP_ERROR_FORMAT,
507517
mapping.endpoint_id, ChipLogValueMEI(dataAttributePath.mClusterId),
508518
ChipLogValueMEI(dataAttributePath.mAttributeId), err.Format());
@@ -691,5 +701,29 @@ void WriteHandler::MoveToState(const State aTargetState)
691701
ChipLogDetail(DataManagement, "IM WH moving to [%s]", GetStateStr());
692702
}
693703

704+
CHIP_ERROR WriteHandler::WriteClusterData(const Access::SubjectDescriptor & subject, const ConcreteDataAttributePath & path,
705+
TLV::TLVReader & data)
706+
{
707+
// Writes do not have a checked-path. If data model interface is enabled (both checked and only version)
708+
// the write is done via the DataModel interface
709+
#if CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
710+
VerifyOrReturnError(mDataModelProvider != nullptr, CHIP_ERROR_INCORRECT_STATE);
711+
712+
DataModel::WriteAttributeRequest request;
713+
714+
request.path = path;
715+
request.subjectDescriptor = subject;
716+
request.writeFlags.Set(DataModel::WriteFlags::kTimed, IsTimedWrite());
717+
718+
AttributeValueDecoder decoder(data, subject);
719+
720+
DataModel::ActionReturnStatus status = mDataModelProvider->WriteAttribute(request, decoder);
721+
722+
return AddStatusInternal(path, StatusIB(status.GetStatusCode()));
723+
#else
724+
return WriteSingleClusterData(subject, path, data, this);
725+
#endif // CHIP_CONFIG_USE_DATA_MODEL_INTERFACE
726+
}
727+
694728
} // namespace app
695729
} // namespace chip

0 commit comments

Comments
 (0)
Please sign in to comment.