From 4c30c82f09454687e7f57fe209d7153f20fee55e Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Tue, 7 May 2024 11:28:48 -0400 Subject: [PATCH 01/39] Clean up AppConfig dependencies (#33333) --- src/controller/tests/TestEventCaching.cpp | 1 - src/controller/tests/TestEventNumberCaching.cpp | 1 - src/controller/tests/TestServerCommandDispatch.cpp | 1 - src/controller/tests/TestWriteChunking.cpp | 1 - src/messaging/ReliableMessageContext.cpp | 8 +++----- src/platform/BUILD.gn | 1 - 6 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/controller/tests/TestEventCaching.cpp b/src/controller/tests/TestEventCaching.cpp index f69f5614592db7..3ff85ebdf96cdc 100644 --- a/src/controller/tests/TestEventCaching.cpp +++ b/src/controller/tests/TestEventCaching.cpp @@ -22,7 +22,6 @@ #include "app/ConcreteAttributePath.h" #include "protocols/interaction_model/Constants.h" #include -#include #include #include #include diff --git a/src/controller/tests/TestEventNumberCaching.cpp b/src/controller/tests/TestEventNumberCaching.cpp index 01526388f4e459..1244a77481209e 100644 --- a/src/controller/tests/TestEventNumberCaching.cpp +++ b/src/controller/tests/TestEventNumberCaching.cpp @@ -19,7 +19,6 @@ #include "app-common/zap-generated/ids/Clusters.h" #include "app/ClusterStateCache.h" #include -#include #include #include #include diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp index 40b4c098ba52e6..a87ec5d1bcd8d3 100644 --- a/src/controller/tests/TestServerCommandDispatch.cpp +++ b/src/controller/tests/TestServerCommandDispatch.cpp @@ -26,7 +26,6 @@ #include "app-common/zap-generated/ids/Clusters.h" #include "protocols/interaction_model/Constants.h" #include -#include #include #include #include diff --git a/src/controller/tests/TestWriteChunking.cpp b/src/controller/tests/TestWriteChunking.cpp index 2190195887ad41..d8c748129a755d 100644 --- a/src/controller/tests/TestWriteChunking.cpp +++ b/src/controller/tests/TestWriteChunking.cpp @@ -21,7 +21,6 @@ #include "app/ConcreteAttributePath.h" #include "protocols/interaction_model/Constants.h" #include -#include #include #include #include diff --git a/src/messaging/ReliableMessageContext.cpp b/src/messaging/ReliableMessageContext.cpp index 30f00a67814a25..882c5423b78a73 100644 --- a/src/messaging/ReliableMessageContext.cpp +++ b/src/messaging/ReliableMessageContext.cpp @@ -23,16 +23,14 @@ #include -#include -#include -#include - -#include #include #include #include #include +#include +#include #include +#include #include #include #include diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 84870e55362c41..16287f1afb16de 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -509,7 +509,6 @@ if (chip_device_platform != "none") { public_deps = [ ":platform_base", - "${chip_root}/src/app:app_config", # TODO: Move into platforms using it "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/crypto", "${chip_root}/src/lib/support", From f4a7cb404dcbbdf20abef4ae34a7f21df3a42f84 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 7 May 2024 15:54:00 +0000 Subject: [PATCH 02/39] [Linux] Add fabric-bridge app to vscode config (#33335) --- .vscode/launch.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index 0ed822ad0251a9..176a184fbf4531 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -402,6 +402,14 @@ "cwd": "${workspaceFolder}" }, + { + "name": "Fabric Bridge App (Linux)", + "type": "lldb", + "request": "launch", + "program": "${workspaceFolder}/out/debug/standalone/fabric-bridge-app", + "cwd": "${workspaceFolder}" + }, + { "name": "OTA Requestor App (Linux)", "type": "lldb", From 36c76e681bd502bcef701e278837909b232efa2d Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 7 May 2024 12:33:15 -0400 Subject: [PATCH 03/39] Define a IM/DM decoupling interface for interaction model engine to interact with the data model bits (#32914) * Start adding a interaction model decoupling * Restyle * Also add invoke responder bits * Add the first model definition, for each operation * Add all files into the build definition * Start adding the side effect support classes to the interaction model definitions * Add actions and integrate them to the IM model * Add iteration methods * Restyle * Add all files to the build definition * Start defining a unit test to at least validate compilation. Will later validate that we get events emitted * Fix a dependency * Move EventLoggingDelegate to be part of "events" in app. - Remove unneeded includes from this header - add dependency to core (due to TLV) * Prepare for testing ... does not compile however TODOs are starting to go away * Fix SFINAE logic on eventing * test that something is actually emitted for events * Tests actually do something * Some tests actually pass * Restyle * Minor style updates * Rename EmitEvent to GenerateEvent * Add description for paths * Cleanup some example text ... we do not need an exhaustive usage list * Restyle * Fix spelling * Renames based on code review: use UpperCamelCase * Updated proposal for retries and paths * Restyle * one more comment * Restyled by clang-format * Fix typo in parameter type * Some updates for code review * Undo submodule update * Fix logic error in buffer-too-small check for buffer data * Fix return error code when send encounters an error * Fix logic for mCompleted handling in the auto-complete handling * More comments * Comments * Use AAI types for interaction model. I think they will need some splitting, however for now they seem to be a solid catch-all * Update some naming to not use the a... syntax since those are odd * Code review updates * Added extra comment * Enforce lifetime in invoke responses * More comments * More comments * Restyle * Added comment on replyasync with nullptr * Update src/app/interaction-model/InvokeResponder.h Co-authored-by: Terence Hampson * Update src/app/interaction-model/InvokeResponder.h Co-authored-by: Terence Hampson * Update src/app/interaction-model/InvokeResponder.h Co-authored-by: Terence Hampson * Update src/app/interaction-model/InvokeResponder.h Co-authored-by: Terence Hampson * Some code review updates * Some code review updates * Make the subject descriptor optional * use std::optional instead of chip optiona * Restyle --------- Co-authored-by: Restyled.io Co-authored-by: Andrei Litvin Co-authored-by: Terence Hampson --- src/BUILD.gn | 1 + src/app/interaction-model/Actions.h | 37 ++ src/app/interaction-model/BUILD.gn | 41 +++ src/app/interaction-model/Events.h | 130 +++++++ src/app/interaction-model/InvokeResponder.h | 316 ++++++++++++++++++ src/app/interaction-model/IterationTypes.h | 94 ++++++ src/app/interaction-model/Model.h | 123 +++++++ src/app/interaction-model/OperationTypes.h | 94 ++++++ src/app/interaction-model/Paths.h | 48 +++ src/app/interaction-model/RequestContext.h | 43 +++ src/app/interaction-model/tests/BUILD.gn | 23 ++ .../tests/TestEventEmitting.cpp | 164 +++++++++ 12 files changed, 1114 insertions(+) create mode 100644 src/app/interaction-model/Actions.h create mode 100644 src/app/interaction-model/BUILD.gn create mode 100644 src/app/interaction-model/Events.h create mode 100644 src/app/interaction-model/InvokeResponder.h create mode 100644 src/app/interaction-model/IterationTypes.h create mode 100644 src/app/interaction-model/Model.h create mode 100644 src/app/interaction-model/OperationTypes.h create mode 100644 src/app/interaction-model/Paths.h create mode 100644 src/app/interaction-model/RequestContext.h create mode 100644 src/app/interaction-model/tests/BUILD.gn create mode 100644 src/app/interaction-model/tests/TestEventEmitting.cpp diff --git a/src/BUILD.gn b/src/BUILD.gn index 61292e14f92612..d1dfcc7856135e 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -55,6 +55,7 @@ if (chip_build_tests) { chip_test_group("tests") { deps = [] tests = [ + "${chip_root}/src/app/interaction-model/tests", "${chip_root}/src/access/tests", "${chip_root}/src/crypto/tests", "${chip_root}/src/inet/tests", diff --git a/src/app/interaction-model/Actions.h b/src/app/interaction-model/Actions.h new file mode 100644 index 00000000000000..62021fbf7ccd32 --- /dev/null +++ b/src/app/interaction-model/Actions.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 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 +#include +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +/// Data provided to data models in order to interface with the interaction model environment. +struct InteractionModelActions +{ + Events * events; + Paths * paths; + RequestContext * requestContext; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/BUILD.gn b/src/app/interaction-model/BUILD.gn new file mode 100644 index 00000000000000..c91c2aedac633e --- /dev/null +++ b/src/app/interaction-model/BUILD.gn @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# 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. +import("//build_overrides/chip.gni") + +source_set("interaction-model") { + sources = [ + "Actions.h", + "Events.h", + "InvokeResponder.h", + "IterationTypes.h", + "Model.h", + "OperationTypes.h", + "Paths.h", + "RequestContext.h", + ] + + public_deps = [ + "${chip_root}/src/access:types", + "${chip_root}/src/app:attribute-access", + "${chip_root}/src/app:events", + "${chip_root}/src/app:paths", + "${chip_root}/src/app/MessageDef", + "${chip_root}/src/app/data-model", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/core:error", + "${chip_root}/src/lib/core:types", + "${chip_root}/src/lib/support", + "${chip_root}/src/messaging", + ] +} diff --git a/src/app/interaction-model/Events.h b/src/app/interaction-model/Events.h new file mode 100644 index 00000000000000..255a55e97ee465 --- /dev/null +++ b/src/app/interaction-model/Events.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +namespace internal { +template +class SimpleEventLoggingDelegate : public EventLoggingDelegate +{ +public: + SimpleEventLoggingDelegate(const T & aEventData) : mEventData(aEventData){}; + CHIP_ERROR WriteEvent(chip::TLV::TLVWriter & aWriter) final override + { + return DataModel::Encode(aWriter, TLV::ContextTag(EventDataIB::Tag::kData), mEventData); + } + +private: + const T & mEventData; +}; + +template ::value, bool> = true> +EventNumber GenerateEvent(E & emittor, const T & aEventData, EndpointId aEndpoint) +{ + internal::SimpleEventLoggingDelegate eventData(aEventData); + ConcreteEventPath path(aEndpoint, aEventData.GetClusterId(), aEventData.GetEventId()); + EventOptions eventOptions; + eventOptions.mPath = path; + eventOptions.mPriority = aEventData.GetPriorityLevel(); + eventOptions.mFabricIndex = aEventData.GetFabricIndex(); + + // this skips logging the event if it's fabric-scoped but no fabric association exists yet. + + if (eventOptions.mFabricIndex == kUndefinedFabricIndex) + { + ChipLogError(EventLogging, "Event encode failure: no fabric index for fabric scoped event"); + return kInvalidEventId; + } + + // + // Unlike attributes which have a different 'EncodeForRead' for fabric-scoped structs, + // fabric-sensitive events don't require that since the actual omission of the event in its entirety + // happens within the event management framework itself at the time of access. + // + // The 'mFabricIndex' field in the event options above is encoded out-of-band alongside the event payload + // and used to match against the accessing fabric. + // + EventNumber eventNumber; + CHIP_ERROR err = emittor.GenerateEvent(&eventData, eventOptions, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(EventLogging, "Failed to log event: %" CHIP_ERROR_FORMAT, err.Format()); + return kInvalidEventId; + } + + return eventNumber; +} + +template ::value, bool> = true> +EventNumber GenerateEvent(E & emittor, const T & aEventData, EndpointId endpointId) +{ + internal::SimpleEventLoggingDelegate eventData(aEventData); + ConcreteEventPath path(endpointId, aEventData.GetClusterId(), aEventData.GetEventId()); + EventOptions eventOptions; + eventOptions.mPath = path; + eventOptions.mPriority = aEventData.GetPriorityLevel(); + EventNumber eventNumber; + CHIP_ERROR err = emittor.GenerateEvent(&eventData, eventOptions, eventNumber); + if (err != CHIP_NO_ERROR) + { + ChipLogError(EventLogging, "Failed to log event: %" CHIP_ERROR_FORMAT, err.Format()); + return kInvalidEventId; + } + + return eventNumber; +} + +} // namespace internal + +class Events +{ +public: + virtual ~Events() = default; + + /// Generates the given event. + /// + /// Events are generally expected to be sent to subscribed clients and also + /// be available for read later until they get overwritten by new events + /// that are being generated. + virtual CHIP_ERROR GenerateEvent(EventLoggingDelegate * eventContentWriter, const EventOptions & options, + EventNumber & generatedEventNumber) = 0; + + // Convenience methods for event logging using cluster-object structures + // On error, these log and return kInvalidEventId + template + EventNumber GenerateEvent(const T & eventData, EndpointId endpointId) + { + return internal::GenerateEvent(*this, eventData, endpointId); + } +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/InvokeResponder.h b/src/app/interaction-model/InvokeResponder.h new file mode 100644 index 00000000000000..0a399b24564e96 --- /dev/null +++ b/src/app/interaction-model/InvokeResponder.h @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2024 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 +#include +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +/// Handles encoding of an invoke response for a specific invoke request. +/// +/// This class handles a single response (i.e. a CommandDataIB within the +/// matter protocol) and is responsible for constructing its corresponding +/// response (i.e. a InvokeResponseIB within the matter protocol) +/// +/// Invoke responses MUST contain exactly ONE of: +/// - response data (accessed via `ResponseEncoder`) +/// - A status, which may be success or failure, both of which may +/// contain a cluster-specific error code. +/// +/// To encode a response, `Complete` MUST be called. +/// +/// `Complete` requirements +/// - Complete with InteractionModel::Status::Success will respond with data +/// some response data was written. +/// - Any other case (including success with cluster specific codes) implies +/// no response data and a status will be encoded instead +/// - this includes the case when some response data was written already. +/// In that case, the response data will be rolled back and only the status +/// will be encoded. +/// +/// Creating a response MAY be retried at most once, if and only if `Complete` +/// returns CHIP_ERROR_BUFFER_TOO_SMALL. Retry attempts MUST not exceed 1: +/// - FlushPendingResponses MUST be called to make as much buffer space as possible +/// available for encoding +/// - The response encoding (including `ResponseEncoder` usage and calling Complete) +/// MUST be retried once more. If the final Complete returns an error, the result +/// of the invoke will be an error status. +/// +class InvokeResponder +{ +public: + virtual ~InvokeResponder() = default; + + // Copying not allowed since underlying requirement is that on deletion of this + // object, a reply will be sent. + InvokeResponder(const InvokeResponder &) = delete; + InvokeResponder & operator=(const InvokeResponder &) = delete; + + /// Flush any pending replies before encoding the current reply. + /// + /// MAY be called at most once. + /// + /// This function is intended to provided the ability to retry sending a reply + /// if a reply encoding fails due to insufficient buffer. + /// + /// Call this if `Complete(...)` returns CHIP_ERROR_BUFFER_TOO_SMALL and try + /// again. If reply data is needed, the complete ResponseEncoder + Complete + /// call chain MUST be re-run. + virtual CHIP_ERROR FlushPendingResponses() = 0; + + /// Reply with a data payload. + /// + /// MUST be called at most once per reply. + /// Can be called a 2nd time after a `FlushPendingResponses()` call + /// + /// - responseCommandId must correspond with the data encoded in the returned encoder + /// - Complete(CHIP_NO_ERROR) MUST be called to flush the reply + /// + /// If encoder returns CHIP_ERROR_BUFFER_TOO_SMALL, FlushPendingResponses should be + /// used to attempt to free up buffer space then encoding should be tried again. + virtual DataModel::WrappedStructEncoder & ResponseEncoder(CommandId responseCommandId) = 0; + + /// Signal completing of the reply. + /// + /// MUST be called exactly once to signal a response is to be recorded to be sent. + /// The error code (and the data encoded by ResponseEncoder) may be buffered for + /// sending among other batched responses. + /// + /// If this returns CHIP_ERROR_BUFFER_TOO_SMALL, this can be called a 2nd time after + /// a FlushPendingResponses. + /// + /// Argument behavior: + /// - Commands can only be replied with ONE of the following (spec 8.9.4.4): + /// - command data (i.e. ResponseEncoder contents) + /// - A status (including success/error/cluster-specific-success-or-error ) + /// - As a result there are two possible paths: + /// - IF a Status::Success is given (WITHOUT cluster specific status), then + /// the data in ResponseEncoder is sent as a reply. If no data was sent, + /// a invoke `Status::Success` with no cluster specific data is sent + /// - OTHERWISE any previously encoded data via ResponseEncoder is discarded + /// and the given reply (success with cluster status or failure) is sent + /// as a reply to the invoke. + /// + /// + /// Returns success/failure state. One error code MUST be handled in particular: + /// + /// - CHIP_ERROR_BUFFER_TOO_SMALL will return IF AND ONLY IF the responder was unable + /// to fully serialize the given reply/error data. + /// + /// If such an error is returned, the caller MUST retry by calling FlushPendingResponses + /// first and then re-encoding the reply content (use ResponseEncoder if applicable and + /// call Complete again) + /// + /// - Any other error (i.e. different from CHIP_NO_ERROR) mean that the invoke response + /// will contain an error and such an error is considered permanent. + /// + virtual CHIP_ERROR Complete(StatusIB error) = 0; +}; + +/// Enforces that once acquired, Complete will be called on the underlying writer +class AutoCompleteInvokeResponder +{ +public: + // non-copyable: once you have a handle, keep it + AutoCompleteInvokeResponder(const AutoCompleteInvokeResponder &) = delete; + AutoCompleteInvokeResponder & operator=(const AutoCompleteInvokeResponder &) = delete; + + AutoCompleteInvokeResponder(InvokeResponder * writer) : mWriter(writer) {} + ~AutoCompleteInvokeResponder() + { + if (mCompleteState != CompleteState::kComplete) + { + mWriter->Complete(Protocols::InteractionModel::Status::Failure); + } + } + + /// Direct access to reply encoding. + /// + /// Use this only in conjunction with the other Raw* calls + DataModel::WrappedStructEncoder & RawResponseEncoder(CommandId replyCommandId) + { + return mWriter->ResponseEncoder(replyCommandId); + } + + /// Direct access to flushing replies + /// + /// Use this only in conjunction with the other Raw* calls + CHIP_ERROR RawFlushPendingReplies() + { + // allow a flush if we never called it (this may not be reasonable, however + // we accept an early flush) or if flush is expected + VerifyOrReturnError((mCompleteState == CompleteState::kNeverCalled) || (mCompleteState == CompleteState::kFlushExpected), + CHIP_ERROR_INCORRECT_STATE); + mCompleteState = CompleteState::kFlushed; + return mWriter->FlushPendingResponses(); + } + + /// Call "Complete" without the automatic retries. + /// + /// Use this in conjunction with the other Raw* calls + CHIP_ERROR RawComplete(StatusIB status) + { + VerifyOrReturnError((mCompleteState == CompleteState::kNeverCalled) || (mCompleteState == CompleteState::kFlushed), + CHIP_ERROR_INCORRECT_STATE); + CHIP_ERROR err = mWriter->Complete(status); + if ((err == CHIP_ERROR_BUFFER_TOO_SMALL) && (mCompleteState == CompleteState::kNeverCalled)) + { + mCompleteState = CompleteState::kFlushExpected; + } + else + { + mCompleteState = CompleteState::kComplete; + } + return err; + } + + /// Complete the given command. + /// + /// Automatically handles retries for sending. + /// Cannot be called after Raw* methods are used. + /// + /// Any error returned by this are final and not retriable + /// as a retry for CHIP_ERROR_BUFFER_TOO_SMALL is already built in. + CHIP_ERROR Complete(StatusIB status) + { + VerifyOrReturnError(mCompleteState == CompleteState::kNeverCalled, CHIP_ERROR_INCORRECT_STATE); + // this is a final complete, including retry handling + mCompleteState = CompleteState::kComplete; + CHIP_ERROR err = mWriter->Complete(status); + + if (err != CHIP_ERROR_BUFFER_TOO_SMALL) + { + return err; + } + + // retry once. Failure to flush is permanent. + ReturnErrorOnFailure(mWriter->FlushPendingResponses()); + return mWriter->Complete(status); + } + + /// Sends the specified data structure as a response + /// + /// This version of the send has built-in RETRY and handles + /// Flush/Complete automatically. + /// Cannot be called after Raw* methods are used. + /// + /// Any error returned by this are final and not retriable + /// as a retry for CHIP_ERROR_BUFFER_TOO_SMALL is already built in. + template + CHIP_ERROR Send(const ReplyData & data) + { + VerifyOrReturnError(mCompleteState == CompleteState::kNeverCalled, CHIP_ERROR_INCORRECT_STATE); + // this is a final complete, including retry handling + mCompleteState = CompleteState::kComplete; + CHIP_ERROR err = data.Encode(ResponseEncoder(ReplyData::GetCommandId())); + if (err != CHIP_ERROR_BUFFER_TOO_SMALL) + { + LogErrorOnFailure(err); + err = mWriter->Complete(StatusIB(err)); + } + if (err != CHIP_ERROR_BUFFER_TOO_SMALL) + { + return err; + } + + // retry once. Failure to flush is permanent. + ReturnErrorOnFailure(mWriter->FlushPendingResponses()); + err = data.Encode(ResponseEncoder(ReplyData::GetCommandId())); + + // If encoding fails, we will end up sending an error back to the other side + // the caller + LogErrorOnFailure(err); + if (err == CHIP_NO_ERROR) + { + err = mWriter->Complete(StatusIB(err)); + } + else + { + // Error in "complete" is not something we can really forward anymore since + // we already got an error in Encode ... just log this. + LogErrorOnFailure(mWriter->Complete(StatusIB(err))); + } + + return err; + } + +private: + // Contract says that complete may only be called twice: + // - initial complete + // - again after a `Flush` + // The states here expect we are in: + // + // +----------------------------Flush---------| + // | v + // NEVER --Complete--> F_EXPECTED --Flush--> FLUSHED --Complete--> COMPLETE + // | ^ + // +-------------(success or permanent error)-----------| + enum class CompleteState + { + kNeverCalled, + kFlushExpected, + kFlushed, + kComplete, + }; + + InvokeResponder * mWriter; + CompleteState mCompleteState = CompleteState::kNeverCalled; +}; + +enum ReplyAsyncFlags +{ + // Some commands that are expensive to process (e.g. crypto). + // Implementations may choose to send an ack on the message right away to + // avoid MRP retransmits. + kSlowCommandHandling = 0x0001, +}; + +class InvokeReply +{ +public: + virtual ~InvokeReply() = default; + + // reply with no data + CHIP_ERROR Reply(StatusIB status) { return this->Reply().Complete(status); } + + // Enqueue the content of the reply at this point in time (rather than Async sending it). + // + // Implementations will often batch several replies into one packet for batch commands, + // so it will be implementation-specific on when the actual reply packet is + // sent. + virtual AutoCompleteInvokeResponder Reply() = 0; + + // Reply "later" to the command. This allows async processing. A reply will be forced + // when the returned InvokeReply is destroyed. + // + // NOTE: Each InvokeReply is associated with a separate `CommandDataIB` within batch + // commands. When replying asynchronously, each InvokeReply will set the response + // data for the given commandpath/ref only. + // + // IF empty pointer is returned, insufficient memory to reply async is available and + // this should be handled (e.g. by returning an error to the handler/replying with + // an errorcode synchronously). + virtual std::unique_ptr ReplyAsync(BitFlags flags) = 0; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/IterationTypes.h b/src/app/interaction-model/IterationTypes.h new file mode 100644 index 00000000000000..32ad8bc42b73be --- /dev/null +++ b/src/app/interaction-model/IterationTypes.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 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 +#include + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +enum class ClusterQualityFlags : uint32_t +{ + kDiagnosticsData = 0x0001, // `K` quality, may be filtered out in subscriptions +}; + +struct ClusterInfo +{ + DataVersion dataVersion; // current version of this cluster + BitFlags flags; +}; + +struct ClusterEntry +{ + ConcreteClusterPath path; + ClusterInfo info; +}; + +enum class AttributeQualityFlags : uint32_t +{ + kListAttribute = 0x0001, // This attribute is a list attribute + kChangesOmitted = 0x0002, // `C` quality on attributes +}; + +struct AttributeInfo +{ + BitFlags flags; +}; + +struct AttributeEntry +{ + ConcreteAttributePath path; + AttributeInfo info; +}; + +/// Provides metadata information for a data model +/// +/// The data model can be viewed as a tree of endpoint/cluster/attribute +/// where each element can be iterated through independently +/// +/// Iteration rules: +/// - kInvalidEndpointId will be returned when iteration ends (or generally kInvalid* for paths) +/// - Any internal iteration errors are just logged (callers do not handle iteration CHIP_ERROR) +/// - Iteration order is NOT guaranteed, however uniqueness and completeness is (must iterate +/// over all possible distinct values as long as no internal structural changes occur) +class AttributeTreeIterator +{ +public: + virtual ~AttributeTreeIterator() = default; + + virtual EndpointId FirstEndpoint() = 0; + virtual EndpointId NextEndpoint(EndpointId before) = 0; + + virtual ClusterEntry FirstCluster(EndpointId endpoint) = 0; + virtual ClusterEntry NextCluster(const ConcreteClusterPath & before) = 0; + virtual std::optional GetClusterInfo(const ConcreteClusterPath & path) = 0; + + virtual AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) = 0; + virtual AttributeEntry NextAttribute(const ConcreteAttributePath & before) = 0; + virtual std::optional GetAttributeInfo(const ConcreteAttributePath & path) = 0; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/Model.h b/src/app/interaction-model/Model.h new file mode 100644 index 00000000000000..b3a127c074aaa1 --- /dev/null +++ b/src/app/interaction-model/Model.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2024 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 +#include + +#include +#include + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +/// Represents operations against a matter-defined data model. +/// +/// Class is SINGLE-THREADED: +/// - operations are assumed to only be ever run in a single event-loop +/// thread or equivalent +/// - class is allowed to attempt to cache indexes/locations for faster +/// lookups of things (e.g during iterations) +class Model : public AttributeTreeIterator +{ +public: + virtual ~Model() = default; + + // `actions` pointers will be guaranteed valid until Shutdown is called() + virtual CHIP_ERROR Startup(InteractionModelActions actions) + { + mActions = actions; + return CHIP_NO_ERROR; + } + virtual CHIP_ERROR Shutdown() = 0; + + // During the transition phase, we expect a large subset of code to require access to + // event emitting, path marking and other operations + virtual InteractionModelActions CurrentActions() { return mActions; } + + /// List reading has specific handling logic: + /// `state` contains in/out data about the current list reading. MUST start with kInvalidListIndex on first call + /// + /// Return codes: + /// CHIP_ERROR_MORE_LIST_DATA_AVAILABLE (NOTE: new error defined for this purpose) + /// - partial data written to the destination + /// - destination will contain AT LEAST one valid list entry fully serialized + /// - destination will be fully valid (it will be rolled back on partial list writes) + /// CHIP_IM_GLOBAL_STATUS(code): + /// - error codes that are translatable in IM status codes (otherwise we expect Failure to be reported) + /// - In particular, some handlers rely on special handling for: + /// - `UnsupportedAccess` - for ACL checks (e.g. wildcard expansion may choose to skip these) + /// - to check for this, CHIP_ERROR provides: + /// - ::IsPart(ChipError::SdkPart::kIMGlobalStatus) -> bool + /// - ::GetSdkCode() -> uint8_t to translate to the actual code + virtual CHIP_ERROR ReadAttribute(const ReadAttributeRequest & request, ReadState & state, AttributeValueEncoder & encoder) = 0; + + /// Requests a write of an attribute. + /// + /// When this is invoked, caller is expected to have already done some validations: + /// - cluster `data version` has been checked for the incoming request if applicable + /// + /// List operation support: + /// - the first list write will have `request.writeFlags.Has(WriteFlags::kListBegin)` + /// - the last list write will have `request.writeFlags.Has(WriteFlags::kListEnd)` + /// - the last list write MAY have empty data (no list items) + /// + /// When `request.writeFlags.Has(WriteFlags::kForceInternal)` the request is from an internal app update + /// and SHOULD bypass some internal checks (like timed enforcement, potentially read-only restrictions) + /// + /// Return codes + /// CHIP_IM_GLOBAL_STATUS(code): + /// - error codes that are translatable to specific IM codes + /// - in particular, the following codes are interesting/expected + /// - `UnsupportedWrite` for attempts to write read-only data + /// - `UnsupportedAccess` for ACL failures + /// - `NeedsTimedInteraction` for writes that are not timed however are required to be so + virtual CHIP_ERROR WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder) = 0; + + /// `responder` is used to send back the reply. + /// - calling Reply() or ReplyAsync() will let the application control the reply + /// - returning a CHIP_NO_ERROR without reply/reply_async implies a Status::Success reply without data + /// - returning a CHIP_*_ERROR implies an error reply (error and data are mutually exclusive) + /// + /// See InvokeReply/AutoCompleteInvokeResponder for details on how to send back replies and expected + /// error handling. If you require knowledge if a response was successfully sent, use the underlying + /// `reply` object instead of returning an error codes from Invoke. + /// + /// Return codes + /// CHIP_IM_GLOBAL_STATUS(code): + /// - error codes that are translatable to specific IM codes + /// - in particular, the following codes are interesting/expected + /// - `UnsupportedEndpoint` for invalid endpoint + /// - `UnsupportedCluster` for no such cluster on the endpoint + /// - `UnsupportedCommand` for no such command in the cluster + /// - `UnsupportedAccess` for permission errors (ACL or fabric scoped with invalid fabric) + /// - `NeedsTimedInteraction` if the invoke requires timed interaction support + virtual CHIP_ERROR Invoke(const InvokeRequest & request, chip::TLV::TLVReader & input_arguments, InvokeReply & reply) = 0; + +private: + InteractionModelActions mActions = { nullptr }; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/OperationTypes.h b/src/app/interaction-model/OperationTypes.h new file mode 100644 index 00000000000000..115dc11a1ff3bc --- /dev/null +++ b/src/app/interaction-model/OperationTypes.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include + +#include +#include + +namespace chip { +namespace app { +namespace InteractionModel { + +/// Contains common flags among all interaction model operations: read/write/invoke +enum class OperationFlags : uint32_t +{ + kInternal = 0x0001, // Internal request for data changes (can bypass checks/ACL etc.) +}; + +/// This information is available for ALL interactions: read/write/invoke +struct OperationRequest +{ + OperationFlags operationFlags; + + /// Current authentication data EXCEPT for internal requests. + /// - Non-internal requests MUST have this set. + /// - operationFlags.Has(OperationFlags::kInternal) MUST NOT have this set + std::optional subjectDescriptor; +}; + +enum class ReadFlags : uint32_t +{ + kFabricFiltered = 0x0001, // reading is performed fabric-filtered +}; + +struct ReadAttributeRequest : OperationRequest +{ + ConcreteAttributePath path; + std::optional dataVersion; + BitFlags readFlags; +}; + +struct ReadState +{ + // When reading lists, reading will start at this index. + // As list data is read, this index is incremented + ListIndex listEncodeStart = kInvalidListIndex; +}; + +enum class WriteFlags : uint32_t +{ + kTimed = 0x0001, // Received as a 2nd command after a timed invoke + kListBegin = 0x0002, // This is the FIRST list data element in a series of data + kListEnd = 0x0004, // This is the LAST list element to write +}; + +struct WriteAttributeRequest : OperationRequest +{ + ConcreteDataAttributePath path; // NOTE: this also contains LIST operation options (i.e. "data" path type) + BitFlags writeFlags; +}; + +enum class InvokeFlags : uint32_t +{ + kTimed = 0x0001, // Received as a 2nd command after a timed invoke +}; + +struct InvokeRequest : OperationRequest +{ + ConcreteCommandPath path; + std::optional groupRequestId; // set if and only if this was a group request + BitFlags invokeFlags; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/Paths.h b/src/app/interaction-model/Paths.h new file mode 100644 index 00000000000000..2bf9f0c4158011 --- /dev/null +++ b/src/app/interaction-model/Paths.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 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 + +namespace chip { +namespace app { +namespace InteractionModel { + +/// Handles path attributes for interaction models. +/// +/// It allows a user of the class to mark specific paths +/// as having changed. The intended use is for some listener to +/// perform operations as a result of something having changed, +/// usually by forwarding updates (e.g. in case of subscriptions +/// that cover that path). +/// +/// Methods on this class MUCH be called from within the matter +/// main loop as they will likely trigger interaction model +/// internal updates and subscription event updates. +class Paths +{ +public: + virtual ~Paths() = 0; + + /// Mark some specific attributes dirty. + /// Wildcards are supported. + virtual void MarkDirty(const AttributePathParams & path) = 0; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/RequestContext.h b/src/app/interaction-model/RequestContext.h new file mode 100644 index 00000000000000..74fa9af9da0fc8 --- /dev/null +++ b/src/app/interaction-model/RequestContext.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 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 + +namespace chip { +namespace app { +namespace InteractionModel { + +// Context for a currently executing request +class RequestContext +{ +public: + virtual ~RequestContext() = default; + + /// Valid ONLY during synchronous handling of a Read/Write/Invoke + /// + /// Used sparingly, however some operations will require these. An example + /// usage is "Operational Credentials aborting communications on removed fabrics" + /// + /// Callers MUST check for null here (e.g. unit tests mocks may set this to + /// nullptr due to object complexity) + virtual Messaging::ExchangeContext * CurrentExchange() = 0; +}; + +} // namespace InteractionModel +} // namespace app +} // namespace chip diff --git a/src/app/interaction-model/tests/BUILD.gn b/src/app/interaction-model/tests/BUILD.gn new file mode 100644 index 00000000000000..c7d36b4f1dcdca --- /dev/null +++ b/src/app/interaction-model/tests/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Project CHIP Authors +# +# 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. +import("//build_overrides/chip.gni") +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + test_sources = [ "TestEventEmitting.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ "${chip_root}/src/app/interaction-model" ] +} diff --git a/src/app/interaction-model/tests/TestEventEmitting.cpp b/src/app/interaction-model/tests/TestEventEmitting.cpp new file mode 100644 index 00000000000000..cb49dc25caa068 --- /dev/null +++ b/src/app/interaction-model/tests/TestEventEmitting.cpp @@ -0,0 +1,164 @@ +/* + * + * Copyright (c) 2024 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 +#include +#include +#include + +#include + +namespace { + +using namespace chip; +using namespace chip::app; +using namespace chip::app::InteractionModel; + +using StartUpEventType = chip::app::Clusters::BasicInformation::Events::StartUp::Type; +using AccessControlEntryChangedType = chip::app::Clusters::AccessControl::Events::AccessControlEntryChanged::Type; + +constexpr uint32_t kFakeSoftwareVersion = 0x1234abcd; + +/// Keeps the "last event" in-memory to allow tests to validate +/// that event writing and encoding worked. +class LogOnlyEvents : public Events +{ +public: + CHIP_ERROR GenerateEvent(EventLoggingDelegate * eventContentWriter, const EventOptions & options, + EventNumber & generatedEventNumber) override + { + TLV::TLVWriter writer; + TLV::TLVType outerType; + writer.Init(mLastEventEncodeBuffer); + + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType)); + ReturnErrorOnFailure(eventContentWriter->WriteEvent(writer)); + ReturnErrorOnFailure(writer.EndContainer(outerType)); + ReturnErrorOnFailure(writer.Finalize()); + mLastEncodedSpan = ByteSpan(mLastEventEncodeBuffer, writer.GetLengthWritten()); + + mLastOptions = options; + generatedEventNumber = ++mCurrentEventNumber; + + return CHIP_NO_ERROR; + } + + EventNumber CurrentEventNumber() const { return mCurrentEventNumber; } + const EventOptions & LastOptions() const { return mLastOptions; } + ByteSpan LastWrittenEvent() const { return mLastEncodedSpan; } + + // This relies on the default encoding of events which uses + // DataModel::Encode on a EventDataIB::Tag::kData + template + CHIP_ERROR DecodeLastEvent(T & dest) + { + // attempt to decode the last encoded event + TLV::TLVReader reader; + TLV::TLVType outerType; + + reader.Init(LastWrittenEvent()); + + ReturnErrorOnFailure(reader.Next()); + ReturnErrorOnFailure(reader.EnterContainer(outerType)); + + ReturnErrorOnFailure(reader.Next()); // MUST be positioned on the first element + ReturnErrorOnFailure(DataModel::Decode(reader, dest)); + + ReturnErrorOnFailure(reader.ExitContainer(outerType)); + + return CHIP_NO_ERROR; + } + +private: + EventNumber mCurrentEventNumber = 0; + EventOptions mLastOptions; + uint8_t mLastEventEncodeBuffer[128]; + ByteSpan mLastEncodedSpan; +}; + +} // namespace + +TEST(TestInteractionModelEventEmitting, TestBasicType) +{ + LogOnlyEvents logOnlyEvents; + Events * events = &logOnlyEvents; + + StartUpEventType event{ kFakeSoftwareVersion }; + + EventNumber n1 = events->GenerateEvent(event, 0 /* EndpointId */); + ASSERT_EQ(n1, logOnlyEvents.CurrentEventNumber()); + ASSERT_EQ(logOnlyEvents.LastOptions().mPath, + ConcreteEventPath(0 /* endpointId */, StartUpEventType::GetClusterId(), StartUpEventType::GetEventId())); + + chip::app::Clusters::BasicInformation::Events::StartUp::DecodableType decoded_event; + CHIP_ERROR err = logOnlyEvents.DecodeLastEvent(decoded_event); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(EventLogging, "Decoding failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + ASSERT_EQ(err, CHIP_NO_ERROR); + ASSERT_EQ(decoded_event.softwareVersion, kFakeSoftwareVersion); + + EventNumber n2 = events->GenerateEvent(event, /* endpointId = */ 1); + ASSERT_EQ(n2, logOnlyEvents.CurrentEventNumber()); + ASSERT_NE(n1, logOnlyEvents.CurrentEventNumber()); + + ASSERT_EQ(logOnlyEvents.LastOptions().mPath, + ConcreteEventPath(1 /* endpointId */, StartUpEventType::GetClusterId(), StartUpEventType::GetEventId())); +} + +TEST(TestInteractionModelEventEmitting, TestFabricScoped) +{ + constexpr NodeId kTestNodeId = 0x12ab; + constexpr uint16_t kTestPasscode = 12345; + constexpr FabricIndex kTestFabricIndex = kMinValidFabricIndex + 10; + static_assert(kTestFabricIndex != kUndefinedFabricIndex); + + LogOnlyEvents logOnlyEvents; + Events * events = &logOnlyEvents; + + AccessControlEntryChangedType event; + event.adminNodeID = chip::app::DataModel::MakeNullable(kTestNodeId); + event.adminPasscodeID = chip::app::DataModel::MakeNullable(kTestPasscode); + + EventNumber n1 = events->GenerateEvent(event, 0 /* EndpointId */); + // encoding without a fabric ID MUST fail for fabric events + ASSERT_EQ(n1, kInvalidEventId); + + event.fabricIndex = kTestFabricIndex; + n1 = events->GenerateEvent(event, /* endpointId = */ 0); + + ASSERT_NE(n1, kInvalidEventId); + ASSERT_EQ(n1, logOnlyEvents.CurrentEventNumber()); + ASSERT_EQ(logOnlyEvents.LastOptions().mPath, + ConcreteEventPath(0 /* endpointId */, AccessControlEntryChangedType::GetClusterId(), + AccessControlEntryChangedType::GetEventId())); + + chip::app::Clusters::AccessControl::Events::AccessControlEntryChanged::DecodableType decoded_event; + CHIP_ERROR err = logOnlyEvents.DecodeLastEvent(decoded_event); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(EventLogging, "Decoding failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + ASSERT_EQ(err, CHIP_NO_ERROR); + ASSERT_EQ(decoded_event.adminNodeID.ValueOr(0), kTestNodeId); + ASSERT_EQ(decoded_event.adminPasscodeID.ValueOr(0), kTestPasscode); + ASSERT_EQ(decoded_event.fabricIndex, kTestFabricIndex); +} From 29e1a1bf77f60b942dbdfcaf1b6cdbbfd3925f38 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 7 May 2024 13:12:14 -0400 Subject: [PATCH 04/39] add enable/disable dnssd tests for the host test build_examples target (#33339) * Add build variant for dnssd * Fix tests * Restyle --------- Co-authored-by: Andrei Litvin --- scripts/build/build/targets.py | 2 ++ scripts/build/builders/host.py | 11 ++++++++++- scripts/build/testdata/all_targets_linux_x64.txt | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index ece157dc7718ff..bf797220032b15 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -184,6 +184,8 @@ def BuildHostTarget(): target.AppendModifier('rpc', enable_rpcs=True) target.AppendModifier('with-ui', imgui_ui=True) target.AppendModifier('evse-test-event', enable_test_event_triggers=['EVSE']).OnlyIfRe('-energy-management') + target.AppendModifier('enable-dnssd-tests', enable_dnssd_tests=True).OnlyIfRe('-tests') + target.AppendModifier('disable-dnssd-tests', enable_dnssd_tests=False).OnlyIfRe('-tests') return target diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index c1c81dbdc30f9c..568e683b2ba440 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -15,6 +15,7 @@ import os from enum import Enum, auto from platform import uname +from typing import Optional from .gn import GnBuilder @@ -298,7 +299,9 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, interactive_mode=True, extra_tests=False, use_nl_fault_injection=False, use_platform_mdns=False, enable_rpcs=False, use_coverage=False, use_dmalloc=False, minmdns_address_policy=None, minmdns_high_verbosity=False, imgui_ui=False, crypto_library: HostCryptoLibrary = None, - enable_test_event_triggers=None): + enable_test_event_triggers=None, + enable_dnssd_tests: Optional[bool] = None + ): super(HostBuilder, self).__init__( root=os.path.join(root, 'examples', app.ExamplePath()), runner=runner) @@ -406,6 +409,12 @@ def __init__(self, root, runner, app: HostApp, board=HostBoard.NATIVE, if 'EVSE' in enable_test_event_triggers: self.extra_gn_options.append('chip_enable_energy_evse_trigger=true') + if enable_dnssd_tests is not None: + if enable_dnssd_tests: + self.extra_gn_options.append('chip_enable_dnssd_tests=true') + else: + self.extra_gn_options.append('chip_enable_dnssd_tests=false') + if self.board == HostBoard.ARM64: if not use_clang: raise Exception("Cross compile only supported using clang") diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index 4bd269b22b07eb..aff956fa31edc2 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -9,7 +9,7 @@ efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,b 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] genio-lighting-app linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang] -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,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] +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,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] linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage][-trustm] From 947dc7ca59a1d6411af0fdc33745043a94de1a3f Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 7 May 2024 14:32:48 -0400 Subject: [PATCH 05/39] Make sure to include ember defines for door lock. (#33341) * Make sure to include ember defines for door lock. Chef was using MATTER_DM_PLUGIN_DOOR_LOCK_SERVER without including relevant headers (and assuming that data model would transitively define them) This does not work anymore, so include app config instead. * Restyle --------- Co-authored-by: Andrei Litvin --- examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp | 1 + examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp | 1 + examples/chef/common/clusters/door-lock/chef-lock-manager.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp b/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp index 90b9fd017b0a01..5f9d3147513f52 100644 --- a/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp +++ b/examples/chef/common/clusters/door-lock/chef-doorlock-stubs.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER diff --git a/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp index c7fe5696d9ba74..b9de799796e0f1 100644 --- a/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp +++ b/examples/chef/common/clusters/door-lock/chef-lock-endpoint.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include diff --git a/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp b/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp index 24505972fb8e41..e6de049a06b236 100644 --- a/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp +++ b/examples/chef/common/clusters/door-lock/chef-lock-manager.cpp @@ -15,6 +15,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #ifdef MATTER_DM_PLUGIN_DOOR_LOCK_SERVER From f33c62bf8842d82af642b27871a263d0a2c3f31c Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Wed, 8 May 2024 03:15:24 +0800 Subject: [PATCH 06/39] Fix crash for eps32 commissioner if ble disconnect during commissioning (#33332) --- src/platform/ESP32/nimble/BLEManagerImpl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index b5d9e662b9706c..54219bfa4d84e6 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -503,6 +503,10 @@ bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const uint8_t value[2]; int rc; struct peer * peer = peer_find(conId); + if (peer == nullptr) + { + return false; + } dsc = peer_dsc_find_uuid(peer, (ble_uuid_t *) (&ShortUUID_CHIPoBLEService), (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX), (ble_uuid_t *) (&ShortUUID_CHIPoBLE_CharTx_Desc)); @@ -537,6 +541,10 @@ bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, cons uint8_t value[2]; int rc; struct peer * peer = peer_find(conId); + if (peer == nullptr) + { + return false; + } dsc = peer_dsc_find_uuid(peer, (ble_uuid_t *) (&ShortUUID_CHIPoBLEService), (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX), (ble_uuid_t *) (&ShortUUID_CHIPoBLE_CharTx_Desc)); From 060143eabdd82829a9766b93d45754ed61f111c2 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 7 May 2024 15:15:58 -0400 Subject: [PATCH 07/39] OPCREDS: Remove all the PICS markers (#33336) Everything in this cluster is mandatory, these steps do not need to be gated on the presence of a PICS, and if the PICS are set incorrectly, these tests will fail in unexpected and hard to debug ways. --- .../certification/Test_TC_OPCREDS_3_2.yaml | 1 - .../certification/Test_TC_OPCREDS_3_4.yaml | 13 ------------- .../certification/Test_TC_OPCREDS_3_5.yaml | 4 ---- .../certification/Test_TC_OPCREDS_3_6.yaml | 1 - .../certification/Test_TC_OPCREDS_3_7.yaml | 16 ---------------- 5 files changed, 35 deletions(-) diff --git a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_2.yaml b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_2.yaml index daf603b235af8d..a4974d02df7e3d 100644 --- a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_2.yaml +++ b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_2.yaml @@ -177,7 +177,6 @@ tests: disabled: true - label: "Step 6: From TH1 read the CurrentFabricIndex" - PICS: OPCREDS.S.A0005 verification: | ./chip-tool operationalcredentials read current-fabric-index 1 0 diff --git a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_4.yaml b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_4.yaml index bddac66fa9b983..e86e2c20a4888d 100644 --- a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_4.yaml +++ b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_4.yaml @@ -74,7 +74,6 @@ tests: "Step 4: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_original ICACValue is to set icac_original" - PICS: OPCREDS.S.C07.Rsp verification: | Verify that the DUT responds with FAILSAFE_REQUIRED @@ -135,7 +134,6 @@ tests: "Step 6: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_original ICACValue is to set icac_original" - PICS: OPCREDS.S.C07.Rsp verification: | Verify that the DUT responds with a NOCResponse with the StatusCode field set to MissingCsr that is status code 4 @@ -151,7 +149,6 @@ tests: - label: "Step 7: TH1 Sends CSRRequest command with the IsForUpdateNOC field set to false" - PICS: OPCREDS.S.C04.Rsp verification: | Verify that the DUT returns a CSRResponse and save as csr_not_update @@ -182,7 +179,6 @@ tests: "Step 9: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_not_for_update ICACValue is to set icac_not_for_update" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -190,7 +186,6 @@ tests: - label: "Step 10: TH1 Sends CSRRequest command with the IsForUpdateNOC field set to true" - PICS: OPCREDS.S.C04.Rsp verification: | disabled: true @@ -199,7 +194,6 @@ tests: "Step 11: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_original ICACValue is to set icac_original" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -225,7 +219,6 @@ tests: "Step 14: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_update_new_root ICACValue is to set icac_update_new_root" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -247,7 +240,6 @@ tests: Credentials cluster with the following fields: NOCValue is set to noc_update_bad_fabric_on_noc ICACValue is to set icac_update_bad_fabric_on_noc" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -269,7 +261,6 @@ tests: Credentials cluster with the following fields: NOCValue is set to noc_update_bad_fabric_on_icac ICACValue is to set icac_update_bad_fabric_on_icac" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -277,7 +268,6 @@ tests: - label: "Step 19: TH1 sends AddTrustedRootCertificate command to DUT again with the RootCACertificate field set to new_root_cert" - PICS: OPCREDS.S.C0b.Rsp verification: | disabled: true @@ -286,7 +276,6 @@ tests: "Step 20: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_update_new_root ICACValue is to set icac_update_new_root" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -314,7 +303,6 @@ tests: - label: "Step 24: TH1 Sends CSRRequest command over PASE with the IsForUpdateNOC field set to true" - PICS: OPCREDS.S.C04.Rsp verification: | disabled: true @@ -332,7 +320,6 @@ tests: "Step 26: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster over PASE with the following fields: NOCValue is set to noc_pase ICACValue is to set icac_pase" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true diff --git a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_5.yaml b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_5.yaml index 178538165c24ff..4fe99d94149f7f 100644 --- a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_5.yaml +++ b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_5.yaml @@ -84,7 +84,6 @@ tests: - label: "Step 5: TH1 Sends CSRRequest command with the IsForUpdateNOC field set to true" - PICS: OPCREDS.S.C04.Rsp verification: | To get csr nonce give below command 2 times in TH(chip-tool) echo hex:$(hexdump -vn32 -e'4/4 "%08X" ' /dev/urandom) @@ -116,7 +115,6 @@ tests: "Step 7: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_update1 ICACValue is to set icac_update1" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true @@ -152,7 +150,6 @@ tests: - label: "Step 12: TH1 Sends CSRRequest command with the IsForUpdateNOC field set to true" - PICS: OPCREDS.S.C04.Rsp verification: | disabled: true @@ -174,7 +171,6 @@ tests: "Step 14: TH1 sends the UpdateNOC command to the Node Operational Credentials cluster with the following fields: NOCValue is set to noc_update2 ICACValue is to set icac_update2" - PICS: OPCREDS.S.C07.Rsp verification: | disabled: true diff --git a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_6.yaml b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_6.yaml index e1d0eb9cb4e18b..62c18cda86b9b1 100644 --- a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_6.yaml +++ b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_6.yaml @@ -38,7 +38,6 @@ tests: - label: "Step 2: TH1 sends RemoveFabric command with Fabric Index as FabricIndex_TH1 to DUT" - PICS: OPCREDS.S.C0a.Rsp verification: | ./chip-tool operationalcredentials remove-fabric 1 1 0 diff --git a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_7.yaml b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_7.yaml index d74827b753538d..f6751e03c3e283 100644 --- a/src/app/tests/suites/certification/Test_TC_OPCREDS_3_7.yaml +++ b/src/app/tests/suites/certification/Test_TC_OPCREDS_3_7.yaml @@ -39,7 +39,6 @@ tests: - label: "Step 1: Factory Reset DUT (to ensure NOC list is empty at the beginning of the following steps)" - PICS: OPCREDS.S.A0000 # verification: "" # Disabling this step, because the test starts with a DUT device that has just been commissioned by the TH1 commissioner disabled: true @@ -56,7 +55,6 @@ tests: - label: "Step 3.1: Save the FabricIndex for TH1 as TH1_Fabric_Index for future use." - PICS: OPCREDS.S.A0001 identity: "alpha" command: "readAttribute" cluster: "Operational Credentials" @@ -68,7 +66,6 @@ tests: "Step 3.2: TH1 does a non-fabric-filtered read of the Fabrics attribute from the Node Operational Credentials cluster. Save the FabricIndex for TH1 as TH1_Fabric_Index for future use." - PICS: OPCREDS.S.A0001 identity: "alpha" command: "readAttribute" cluster: "Operational Credentials" @@ -83,7 +80,6 @@ tests: - label: "Step 4: TH1 sends ArmFailSafe command to the DUT with the ExpiryLengthSeconds field set to 60 seconds" - PICS: CGEN.S.C00.Rsp && CGEN.S.C01.Tx identity: "alpha" cluster: "General Commissioning" command: "ArmFailSafe" @@ -100,7 +96,6 @@ tests: # verification: "Verify that the DUT sends ArmFailSafeResponse command to TH1 with field ErrorCode as OK(0)" - label: "Step 5: TH1 Sends CSRRequest command with a random 32-byte nonce." - PICS: OPCREDS.S.C04.Rsp identity: "alpha" command: "CSRRequest" cluster: "Operational Credentials" @@ -119,7 +114,6 @@ tests: - label: "Step 6.1: Read the commissioner root certificate from TH2's fabric. Save RCAC as Root_CA_Certificate_TH2" - # PICS: identity: "beta" cluster: "CommissionerCommands" command: "GetCommissionerRootCertificate" @@ -135,7 +129,6 @@ tests: TH2. Save ICAC as Intermediate_Certificate_TH2. Save NOC as Node_Operational_Certificate_TH2. Save IPK as IPK_TH2. Extract the RCAC public key and save as Root_Public_Key_TH2." - # PICS: identity: "beta" cluster: "CommissionerCommands" command: "IssueNocChain" @@ -156,7 +149,6 @@ tests: # verification: "" - label: "Step 7.1: Read the commissioner node ID from TH2" - # PICS: identity: "beta" cluster: "CommissionerCommands" command: "GetCommissionerNodeId" @@ -169,7 +161,6 @@ tests: - label: "Step 7.2: TH1 sends AddTrustedRootCertificate command to DUT with RootCACertificate set to Root_CA_Certificate_TH2" - PICS: OPCREDS.S.C0b.Rsp identity: "alpha" command: "AddTrustedRootCertificate" cluster: "Operational Credentials" @@ -184,7 +175,6 @@ tests: fields: NOCValue as Node_Operational_Certificate_TH2. ICACValue as Intermediate_Certificate_TH2. IpkValue as IPK_TH2. CaseAdminSubject as the NodeID of TH2. AdminVendorId as the Vendor ID of TH2." - PICS: OPCREDS.S.C06.Rsp && OPCREDS.S.C08.Tx identity: "alpha" command: "AddNOC" cluster: "Operational Credentials" @@ -207,14 +197,12 @@ tests: # verification: "Verify that DUT responds with NOCResponse with status code OK" - label: "Step 9: TH2 starts discovery of DUT using Operational Discovery" - # PICS: "" # verification: "" # Disabling this step as this occurs from the AddNOC command being run disabled: true - label: "Step 10: TH2 opens a CASE session with DUT over operational network." - # PICS: "" identity: "beta" cluster: "DelayCommands" command: "WaitForCommissionee" @@ -225,7 +213,6 @@ tests: # verification: "DUT is able to open the CASE session with TH2" - label: "Step 11: TH2 sends CommissioningComplete command" - PICS: CGEN.S.C05.Tx nodeId: 0x43211234 identity: "beta" cluster: "General Commissioning" @@ -240,7 +227,6 @@ tests: "Step 12: TH2 reads the Current Fabric Index attribute from the Node Operational Credentials cluster. Save the FabricIndex for TH2 as TH2_Fabric_Index." - PICS: OPCREDS.S.A0001 identity: "beta" nodeId: 0x43211234 command: "readAttribute" @@ -253,7 +239,6 @@ tests: - label: "Step 13: TH2 does a non-fabric-filtered read of the Fabrics attribute from the Node Operational Credentials cluster" - PICS: OPCREDS.S.A0001 identity: "beta" nodeId: 0x43211234 command: "readAttribute" @@ -273,7 +258,6 @@ tests: - label: "Step 14: TH1 sends RemoveFabric command to DUT with the FabricIndex field set to TH2_Fabric_Index." - PICS: OPCREDS.S.C0a.Rsp identity: "alpha" command: "RemoveFabric" cluster: "Operational Credentials" From a2ded0f40c20af2c3397df6e70adaac1fcb22b4e Mon Sep 17 00:00:00 2001 From: Philip Gregor <147669098+pgregorr-amazon@users.noreply.github.com> Date: Tue, 7 May 2024 12:41:05 -0700 Subject: [PATCH 08/39] Linux tv-casting-app v1.3 IdentificationDeclaration message (#33283) --- .../casting/DiscoveryExampleFragment.java | 5 +- .../jni/cpp/core/MatterCastingPlayer-JNI.cpp | 23 +++- .../MatterTvCastingBridge/MCCastingPlayer.mm | 16 ++- .../linux/simple-app-helper.cpp | 60 +++++++-- .../tv-casting-app/linux/simple-app-helper.h | 1 + .../tv-casting-app/tv-casting-common/BUILD.gn | 1 + .../tv-casting-common/core/CastingApp.cpp | 15 +++ .../tv-casting-common/core/CastingPlayer.cpp | 37 +++-- .../tv-casting-common/core/CastingPlayer.h | 23 ++-- .../core/CommissionerDeclarationHandler.cpp | 49 +++++++ .../core/CommissionerDeclarationHandler.h | 49 +++++++ .../core/IdentificationDeclarationOptions.h | 126 ++++++++++++++++++ .../include/CHIPProjectAppConfig.h | 4 + .../tv-casting-common/support/AppParameters.h | 1 + src/app/server/Server.cpp | 2 +- .../UserDirectedCommissioningServer.cpp | 1 + 16 files changed, 368 insertions(+), 45 deletions(-) create mode 100644 examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp create mode 100644 examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h create mode 100644 examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java index a706780c5be3b4..65d670584971aa 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java @@ -327,8 +327,9 @@ public View getView(int i, View view, ViewGroup viewGroup) { TAG, "OnClickListener.onClick() called for CastingPlayer with deviceId: " + castingPlayer.getDeviceId()); - DiscoveryExampleFragment.Callback callback1 = (DiscoveryExampleFragment.Callback) context; - callback1.handleConnectionButtonClicked(castingPlayer); + DiscoveryExampleFragment.Callback onClickCallback = + (DiscoveryExampleFragment.Callback) context; + onClickCallback.handleConnectionButtonClicked(castingPlayer); }; playerDescription.setOnClickListener(clickListener); return view; diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp index caa64b4ac8d717..1c4a949c9f7cc5 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp @@ -53,9 +53,14 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) CastingPlayer * castingPlayer = support::convertCastingPlayerFromJavaToCpp(thiz); VerifyOrReturnValue(castingPlayer != nullptr, support::convertMatterErrorFromCppToJava(CHIP_ERROR_INVALID_ARGUMENT)); + matter::casting::core::IdentificationDeclarationOptions idOptions; + + // TODO: In the following PRs. Replace EndpointFilter Java class with IdentificationDeclarationOptions Java class. matter::casting::core::EndpointFilter desiredEndpointFilter; if (desiredEndpointFilterJavaObject != nullptr) { + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + // Convert the EndpointFilter Java class to a C++ EndpointFilter jclass endpointFilterJavaClass = env->GetObjectClass(desiredEndpointFilterJavaObject); jfieldID vendorIdFieldId = env->GetFieldID(endpointFilterJavaClass, "vendorId", "Ljava/lang/Integer;"); @@ -66,20 +71,28 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) // "Ljava/util/List;"); // Value of 0 means unspecified - desiredEndpointFilter.vendorId = vendorIdIntegerObject != nullptr + targetAppInfo.vendorId = vendorIdIntegerObject != nullptr ? static_cast(env->CallIntMethod( vendorIdIntegerObject, env->GetMethodID(env->GetObjectClass(vendorIdIntegerObject), "intValue", "()I"))) : 0; - desiredEndpointFilter.productId = productIdIntegerObject != nullptr + targetAppInfo.productId = productIdIntegerObject != nullptr ? static_cast(env->CallIntMethod( productIdIntegerObject, env->GetMethodID(env->GetObjectClass(productIdIntegerObject), "intValue", "()I"))) : 0; - // TODO: In following PRs. Translate the Java requiredDeviceTypes list to a C++ requiredDeviceTypes vector. For now we're - // passing an empty list of DeviceTypeStruct. + + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) + { + ChipLogError(AppServer, + "MatterCastingPlayer-JNI::verifyOrEstablishConnection() failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, + result.Format()); + } } MatterCastingPlayerJNIMgr().mConnectionSuccessHandler.SetUp(env, jSuccessCallback); MatterCastingPlayerJNIMgr().mConnectionFailureHandler.SetUp(env, jFailureCallback); + + // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter. castingPlayer->VerifyOrEstablishConnection( [](CHIP_ERROR err, CastingPlayer * playerPtr) { ChipLogProgress(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() ConnectCallback called"); @@ -96,7 +109,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) MatterCastingPlayerJNIMgr().mConnectionFailureHandler.Handle(err); } }, - static_cast(commissioningWindowTimeoutSec), desiredEndpointFilter); + static_cast(commissioningWindowTimeoutSec), idOptions); return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR); } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index b69bbfb99f9bd7..3bc72235a86c72 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -52,19 +52,29 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue]; dispatch_sync(workQueue, ^{ + matter::casting::core::IdentificationDeclarationOptions idOptions; + + // TODO: In the following PRs. Replace EndpointFilter objC class with IdentificationDeclarationOptions objC class. __block matter::casting::core::EndpointFilter cppDesiredEndpointFilter; if (desiredEndpointFilter != nil) { - cppDesiredEndpointFilter.vendorId = desiredEndpointFilter.vendorId; - cppDesiredEndpointFilter.productId = desiredEndpointFilter.productId; + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + targetAppInfo.vendorId = desiredEndpointFilter.vendorId; + targetAppInfo.productId = desiredEndpointFilter.productId; + + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) { + ChipLogError(AppServer, "MCCastingPlayer.verifyOrEstablishConnectionWithCompletionBlock failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); + } } + // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter. _cppCastingPlayer->VerifyOrEstablishConnection( [completion](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { dispatch_queue_t clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; dispatch_async(clientQueue, ^{ completion(err == CHIP_NO_ERROR ? nil : [MCErrorUtils NSErrorFromChipError:err]); }); - }, timeout, cppDesiredEndpointFilter); + }, timeout, idOptions); }); } diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index de8c255366cd37..ceb66233a7bc6d 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -49,8 +49,10 @@ void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::StrongGetId(), err.Format())); - ChipLogProgress(AppServer, "ConnectionHandler: Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId()); + ChipLogProgress(AppServer, "ConnectionHandler(): Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId()); + ChipLogProgress(AppServer, "ConnectionHandler(): Triggering demo interactions with CastingPlayer(ID: %s)", + castingPlayer->GetId()); std::vector> endpoints = castingPlayer->GetEndpoints(); // Find the desired Endpoint and auto-trigger some Matter Casting demo interactions @@ -219,18 +223,18 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) } if (strcmp(argv[0], "discover") == 0) { - ChipLogProgress(AppServer, "discover"); + ChipLogProgress(AppServer, "CommandHandler() discover"); return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StartDiscovery(kTargetPlayerDeviceType); } if (strcmp(argv[0], "stop-discovery") == 0) { - ChipLogProgress(AppServer, "stop-discovery"); + ChipLogProgress(AppServer, "CommandHandler() stop-discovery"); return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery(); } if (strcmp(argv[0], "request") == 0) { - ChipLogProgress(AppServer, "request"); + ChipLogProgress(AppServer, "CommandHandler() request"); if (argc < 2) { return PrintAllCommands(); @@ -243,10 +247,40 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) ChipLogError(AppServer, "Invalid casting player index provided: %lu", index)); std::shared_ptr targetCastingPlayer = castingPlayers.at(index); - matter::casting::core::EndpointFilter desiredEndpointFilter; - desiredEndpointFilter.vendorId = kDesiredEndpointVendorId; + matter::casting::core::IdentificationDeclarationOptions idOptions; + if (argc == 3) + { + if (strcmp(argv[2], "cgp") == 0) + { + // Attempt Commissioner-Generated Passcode (cgp) commissioning flow only if the CastingPlayer indicates support for + // it. + if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode()) + { + ChipLogProgress( + AppServer, + "CommandHandler() request %lu cgp. Attempting the Commissioner-Generated Passcode commissioning flow", + index); + idOptions.mCommissionerPasscode = true; + } + else + { + ChipLogError(AppServer, + "CommandHandler() request %lu cgp. Selected CastingPLayer does not support the " + "Commissioner-Generated Passcode commissioning flow", + index); + } + } + } + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + targetAppInfo.vendorId = kDesiredEndpointVendorId; + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); + } + targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler, matter::casting::core::kCommissioningWindowTimeoutSec, - desiredEndpointFilter); + idOptions); return CHIP_NO_ERROR; } if (strcmp(argv[0], "print-bindings") == 0) @@ -280,8 +314,12 @@ CHIP_ERROR PrintAllCommands() " delete-fabric Delete a fabric from the casting client's fabric store. Usage: cast delete-fabric 1\r\n"); streamer_printf(sout, " discover Discover Casting Players. Usage: cast discover\r\n"); streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n"); - streamer_printf( - sout, " request Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n"); + streamer_printf(sout, + " request Request connecting to discovered Casting Player with [index] using the " + "Commissionee-Generated Passcode commissioning flow. Usage: cast request 0\r\n"); + streamer_printf(sout, + " request cgp Request connecting to discovered Casting Player with [index] using the " + "Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n"); streamer_printf(sout, "\r\n"); return CHIP_NO_ERROR; diff --git a/examples/tv-casting-app/linux/simple-app-helper.h b/examples/tv-casting-app/linux/simple-app-helper.h index b1dbbe60cf04b3..f8826b5dfe021f 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.h +++ b/examples/tv-casting-app/linux/simple-app-helper.h @@ -20,6 +20,7 @@ #include "core/CastingPlayer.h" #include "core/CastingPlayerDiscovery.h" +#include "core/IdentificationDeclarationOptions.h" #include "core/Types.h" #include diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index 72f14fb7bffeee..a58d272abe88bf 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -106,6 +106,7 @@ chip_data_model("tv-casting-common") { "core/CastingPlayerDiscovery.cpp", "core/CastingPlayerDiscovery.h", "core/Command.h", + "core/CommissionerDeclarationHandler.cpp", "core/Endpoint.cpp", "core/Endpoint.h", "core/Types.h", diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index f7865910832ec9..7e000134190daf 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -18,6 +18,7 @@ #include "CastingApp.h" +#include "CommissionerDeclarationHandler.h" #include "support/CastingStore.h" #include "support/ChipDeviceEventHandler.h" @@ -100,6 +101,9 @@ CHIP_ERROR CastingApp::Start() // reconnect (or verify connection) to the CastingPlayer that the app was connected to before being stopped, if any if (CastingPlayer::GetTargetCastingPlayer() != nullptr) { + ChipLogProgress( + Discovery, + "CastingApp::Start() calling VerifyOrEstablishConnection() to reconnect (or verify connection) to a CastingPlayer"); CastingPlayer::GetTargetCastingPlayer()->VerifyOrEstablishConnection( [](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { if (err != CHIP_NO_ERROR) @@ -136,6 +140,12 @@ CHIP_ERROR CastingApp::PostStartRegistrations() // Register DeviceEvent Handler ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0)); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT + // Set a handler for Commissioner's CommissionerDeclaration messages. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( + CommissionerDeclarationHandler::GetInstance()); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT + mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING return CHIP_NO_ERROR; } @@ -145,6 +155,11 @@ CHIP_ERROR CastingApp::Stop() ChipLogProgress(Discovery, "CastingApp::Stop() called"); VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT + // Remove the handler previously set for Commissioner's CommissionerDeclaration messages. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT + // Shutdown the Matter server chip::Server::GetInstance().Shutdown(); diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index c9f938dbc695c7..0f455d6b4c9a44 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -30,7 +30,7 @@ namespace core { CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr; void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec, - EndpointFilter desiredEndpointFilter) + IdentificationDeclarationOptions idOptions) { ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called"); @@ -50,12 +50,14 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns mOnCompleted = onCompleted; mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec; mTargetCastingPlayer = this; + mIdOptions = idOptions; // If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present // in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any, - // as per desiredEndpointFilter, simply Find or Re-establish the CASE session and return early + // as per IdentificationDeclarationOptions.mTargetAppInfos, simply Find or Re-establish the CASE session and return early. if (cachedCastingPlayers.size() != 0) { + ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Re-establishing CASE with cached CastingPlayer"); it = std::find_if(cachedCastingPlayers.begin(), cachedCastingPlayers.end(), [this](const core::CastingPlayer & castingPlayerParam) { return castingPlayerParam == *this; }); @@ -63,7 +65,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns if (it != cachedCastingPlayers.end()) { unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it); - if (ContainsDesiredEndpoint(&cachedCastingPlayers[index], desiredEndpointFilter)) + if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.getTargetAppInfoList())) { ChipLogProgress( AppServer, @@ -163,14 +165,15 @@ void CastingPlayer::RegisterEndpoint(const memory::Strong endpoint) #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() { + ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest()"); chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest(); VerifyOrReturnValue(ipAddressToUse != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(AppServer, "No IP Address found to send UDC request to")); ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true)); - // TODO: expose options to the higher layer - chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id = mIdOptions.buildIdentificationDeclarationMessage(); + ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); @@ -216,21 +219,27 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC connectionContext->mOnConnectionFailureCallback); } -bool CastingPlayer::ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter) +bool CastingPlayer::ContainsDesiredTargetApp( + core::CastingPlayer * cachedCastingPlayer, + std::vector desiredTargetApps) { std::vector> cachedEndpoints = cachedCastingPlayer->GetEndpoints(); - for (const auto & cachedEndpoint : cachedEndpoints) + for (size_t i = 0; i < desiredTargetApps.size(); i++) { - bool match = true; - match = match && (desiredEndpointFilter.vendorId == 0 || cachedEndpoint->GetVendorId() == desiredEndpointFilter.vendorId); - match = - match && (desiredEndpointFilter.productId == 0 || cachedEndpoint->GetProductId() == desiredEndpointFilter.productId); - // TODO: check deviceTypeList - if (match) + for (const auto & cachedEndpoint : cachedEndpoints) { - return true; + bool match = true; + match = match && (desiredTargetApps[i].vendorId == 0 || cachedEndpoint->GetVendorId() == desiredTargetApps[i].vendorId); + match = + match && (desiredTargetApps[i].productId == 0 || cachedEndpoint->GetProductId() == desiredTargetApps[i].productId); + if (match) + { + ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer found"); + return true; + } } } + ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer not found"); return false; } diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h index 783d50f60af390..2748eafc22cc7e 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -18,7 +18,9 @@ #pragma once +#include "CommissionerDeclarationHandler.h" #include "Endpoint.h" +#include "IdentificationDeclarationOptions.h" #include "Types.h" #include "support/ChipDeviceEventHandler.h" #include "support/EndpointListLoader.h" @@ -123,13 +125,15 @@ class CastingPlayer : public std::enable_shared_from_this * For failure - called back with an error and nullptr. * @param commissioningWindowTimeoutSec (Optional) time (in sec) to keep the commissioning window open, if commissioning is * required. Needs to be >= kCommissioningWindowTimeoutSec. - * @param desiredEndpointFilter (Optional) Attributes (such as VendorId) describing an Endpoint that the client wants to - * interact with after commissioning. If this value is passed in, the VerifyOrEstablishConnection will force User Directed - * Commissioning, in case the desired Endpoint is not found in the on device CastingStore. + * @param idOptions (Optional) Parameters in the IdentificationDeclaration message sent by the Commissionee to the Commissioner. + * These parameters specify the information relating to the requested commissioning session. + * Furthermore, attributes (such as VendorId) describe the TargetApp that the client wants to interact with after commissioning. + * If this value is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the desired + * TargetApp is not found in the on-device CastingStore. */ void VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec, - EndpointFilter desiredEndpointFilter = EndpointFilter()); + IdentificationDeclarationOptions idOptions = IdentificationDeclarationOptions()); /** * @brief Sets the internal connection state of this CastingPlayer to "disconnected" @@ -197,6 +201,7 @@ class CastingPlayer : public std::enable_shared_from_this std::vector> mEndpoints; ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED; CastingPlayerAttributes mAttributes; + IdentificationDeclarationOptions mIdOptions; static CastingPlayer * mTargetCastingPlayer; unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; ConnectCallback mOnCompleted = {}; @@ -217,12 +222,12 @@ class CastingPlayer : public std::enable_shared_from_this #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT /** - * @brief Checks if the cachedCastingPlayer contains an Endpoint that matches the description of the desiredEndpointFilter - * - * @return true - cachedCastingPlayer contains at least one endpoint that matches all the (non-default) values in - * desiredEndpointFilter, false otherwise + * @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list. + * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values for vendorID and + * productID as described in the desiredTargetApps list, false otherwise. */ - bool ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter); + bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, + std::vector desiredTargetApps); // ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with // and connect to a CastingPlayer diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp new file mode 100644 index 00000000000000..1bedc6ce316a39 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2024 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 "CommissionerDeclarationHandler.h" + +#include "Types.h" + +namespace matter { +namespace casting { +namespace core { + +CommissionerDeclarationHandler * CommissionerDeclarationHandler::sCommissionerDeclarationHandler_ = nullptr; + +CommissionerDeclarationHandler * CommissionerDeclarationHandler::GetInstance() +{ + if (sCommissionerDeclarationHandler_ == nullptr) + { + sCommissionerDeclarationHandler_ = new CommissionerDeclarationHandler(); + } + return sCommissionerDeclarationHandler_; +} + +// TODO: In the following PRs. Implement setHandler() for CommissionerDeclaration messages and expose messages to higher layers for +// Linux, Android and iOS. +void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage( + const chip::Transport::PeerAddress & source, chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) +{ + ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called TODO: handle message"); + cd.DebugLog(); +} + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h new file mode 100644 index 00000000000000..e84ca59a59e23d --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2024 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 "Types.h" + +namespace matter { +namespace casting { +namespace core { + +/** + * @brief React to the Commissioner's CommissionerDeclaration messages with this singleton. + */ +class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler +{ +public: + CommissionerDeclarationHandler(const CommissionerDeclarationHandler &) = delete; + void operator=(const CommissionerDeclarationHandler &) = delete; + + static CommissionerDeclarationHandler * GetInstance(); + + void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, + chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override; + +private: + static CommissionerDeclarationHandler * sCommissionerDeclarationHandler_; + CommissionerDeclarationHandler() {} + ~CommissionerDeclarationHandler() {} +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h new file mode 100644 index 00000000000000..af1ae2aaa79d62 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h @@ -0,0 +1,126 @@ +/* + * + * Copyright (c) 2024 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 "Types.h" +#include + +namespace matter { +namespace casting { +namespace core { + +/** + * This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the + * Commissioner. The options specify information relating to the requested UDC commissioning session. + */ +class IdentificationDeclarationOptions +{ +public: + /** + * Feature: Target Content Application + * Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message + * if a commissioning Passcode is needed. + */ + bool mNoPasscode = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the + * Commissioner has been shown to the user. + */ + bool mCdUponPasscodeDialog = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning. + */ + bool mCommissionerPasscode = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready + * for commissioning. + */ + bool mCommissionerPasscodeReady = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to indicate when the Commissionee user has decided to exit the commissioning process. + */ + bool mCancelPasscode = false; + + CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo & targetAppInfo) + { + if (mTargetAppInfos.size() >= CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS) + { + ChipLogError(AppServer, + "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %d", + CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS); + return CHIP_ERROR_NO_MEMORY; + } + + mTargetAppInfos.push_back(targetAppInfo); + return CHIP_NO_ERROR; + } + + std::vector getTargetAppInfoList() const { return mTargetAppInfos; } + + /** + * @brief Builds an IdentificationDeclaration message to be sent to a CastingPlayer, given the options state specified in this + * object. + */ + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration buildIdentificationDeclarationMessage() + { + ChipLogProgress(AppServer, "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage()"); + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + + std::vector targetAppInfos = getTargetAppInfoList(); + for (size_t i = 0; i < targetAppInfos.size(); i++) + { + id.AddTargetAppInfo(targetAppInfos[i]); + } + id.SetNoPasscode(mNoPasscode); + id.SetCdUponPasscodeDialog(mCdUponPasscodeDialog); + id.SetCancelPasscode(mCancelPasscode); + + ChipLogProgress(AppServer, + "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscode: %s", + mCommissionerPasscode ? "true" : "false"); + id.SetCommissionerPasscode(mCommissionerPasscode); + + ChipLogProgress(AppServer, + "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscodeReady: %s", + mCommissionerPasscodeReady ? "true" : "false"); + if (mCommissionerPasscodeReady) + { + id.SetCommissionerPasscodeReady(true); + mCommissionerPasscodeReady = false; + } + return id; + } + +private: + /** + * Feature: Target Content Application + * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication. + * Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the + * desired TargetApp is not found in the on-device CastingStore. + */ + std::vector mTargetAppInfos; +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h index 74926b00489703..f5887bc3828b08 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h +++ b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h @@ -53,6 +53,10 @@ #define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0 +// TVs can handle the memory impact of supporting a larger list of target apps. See +// examples/tv-app/tv-common/include/CHIPProjectAppConfig.h +#define CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS 10 + // For casting, we need to allow more ACL entries, and more complex entries #define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY 20 #define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY 20 diff --git a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h index 9539a2919a81f5..080011f8953c37 100644 --- a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h +++ b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h @@ -42,6 +42,7 @@ class AppParameters chip::Credentials::DeviceAttestationCredentialsProvider * deviceAttestationCredentialsProvider, chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier, ServerInitParamsProvider * serverInitParamsProvider) + // TODO: In the following PRs. Add CommissionerDeclarationHandler. { VerifyOrReturnError(commissionableDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(deviceAttestationCredentialsProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 1ad98d271262da..ad085d52be8a22 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -621,7 +621,7 @@ void Server::Shutdown() CHIP_ERROR Server::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner, Protocols::UserDirectedCommissioning::IdentificationDeclaration & id) { - ChipLogDetail(AppServer, "SendUserDirectedCommissioningRequest2"); + ChipLogDetail(AppServer, "Server::SendUserDirectedCommissioningRequest()"); CHIP_ERROR err; diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp index a06bffcec62b3a..fb31049d1d99a9 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp @@ -367,6 +367,7 @@ CHIP_ERROR IdentificationDeclaration::ReadPayload(uint8_t * udcPayload, size_t p { ChipLogProgress(AppServer, "TLV end of array"); ReturnErrorOnFailure(reader.ExitContainer(listContainerType)); + err = CHIP_NO_ERROR; } } break; From a2792ffdeaacb07df9ef687b579f43ae6e14e090 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 7 May 2024 16:19:08 -0400 Subject: [PATCH 09/39] Switch unit test to a larger EFR32 part as otherwise we run out of flash space (#33347) Co-authored-by: Andrei Litvin --- integrations/cloudbuild/smoke-test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index 524e6d58276a41..d418f9cd2ec63c 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -77,7 +77,7 @@ steps: --target efr32-brd4161a-light-rpc --target efr32-brd4161a-lock-openthread-mtd --target efr32-brd4161a-lock-rpc-openthread-mtd - --target efr32-brd4161a-unit-test + --target efr32-brd4187c-unit-test build --create-archives /workspace/artifacts/ waitFor: From 6090618624187d2d05cad9b741534b8bb1832fe2 Mon Sep 17 00:00:00 2001 From: Yuanyao Zhong <82843247+yyzhong-g@users.noreply.github.com> Date: Tue, 7 May 2024 16:19:47 -0400 Subject: [PATCH 10/39] Remove dependency of InteractionModelEngine in CommandHandler (#31830) * Remove dependency of InteractionModelEngine in CommandHandler * Address comments and fix tizen test * Fix tizen example * Fix segfault in CommandHandler::Handle::Get() * Change CommandHandler::Callback function name * Add virtual function in CommandHandler::Callback in CommandResponseSender * Add mpCallback null checks * Add weak reference to CommandHandler * Remove magic number from ImEngine * self clean up * Restyled by clang-format * Use IntrusiveList for weak references of the Handles * Update src/app/CommandHandler.cpp Co-authored-by: Boris Zbarsky * Update src/app/CommandHandler.cpp Co-authored-by: Boris Zbarsky * Update src/app/CommandHandler.h Co-authored-by: Boris Zbarsky * compile fix after renaming --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- src/app/CommandHandler.cpp | 63 ++++++++++++++++++++++-------- src/app/CommandHandler.h | 45 ++++++++++++++------- src/app/InteractionModelEngine.cpp | 4 -- src/app/InteractionModelEngine.h | 9 ----- 4 files changed, 78 insertions(+), 43 deletions(-) diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp index 005067c96bd7c4..89ff52f9669d2e 100644 --- a/src/app/CommandHandler.cpp +++ b/src/app/CommandHandler.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,11 @@ CommandHandler::CommandHandler(TestOnlyOverrides & aTestOverride, Callback * apC } } +CommandHandler::~CommandHandler() +{ + InvalidateHandles(); +} + CHIP_ERROR CommandHandler::AllocateBuffer() { // We should only allocate a buffer if we will be sending out a response. @@ -266,6 +272,7 @@ void CommandHandler::Close() // reference is the stack shutting down, in which case Close() is not called. So the below check should always pass. VerifyOrDieWithMsg(mPendingWork == 0, DataManagement, "CommandHandler::Close() called with %u unfinished async work items", static_cast(mPendingWork)); + InvalidateHandles(); if (mpCallback) { @@ -273,16 +280,40 @@ void CommandHandler::Close() } } -void CommandHandler::IncrementHoldOff() +void CommandHandler::AddToHandleList(Handle * apHandle) +{ + mpHandleList.PushBack(apHandle); +} + +void CommandHandler::RemoveFromHandleList(Handle * apHandle) +{ + VerifyOrDie(mpHandleList.Contains(apHandle)); + mpHandleList.Remove(apHandle); +} + +void CommandHandler::InvalidateHandles() +{ + for (auto handle = mpHandleList.begin(); handle != mpHandleList.end(); ++handle) + { + handle->Invalidate(); + } +} + +void CommandHandler::IncrementHoldOff(Handle * apHandle) { mPendingWork++; + AddToHandleList(apHandle); } -void CommandHandler::DecrementHoldOff() +void CommandHandler::DecrementHoldOff(Handle * apHandle) { + mPendingWork--; ChipLogDetail(DataManagement, "Decreasing reference count for CommandHandler, remaining %u", static_cast(mPendingWork)); + + RemoveFromHandleList(apHandle); + if (mPendingWork != 0) { return; @@ -771,35 +802,35 @@ FabricIndex CommandHandler::GetAccessingFabricIndex() const return mpResponder->GetAccessingFabricIndex(); } +void CommandHandler::Handle::Init(CommandHandler * handler) +{ + if (handler != nullptr) + { + handler->IncrementHoldOff(this); + mpHandler = handler; + } +} + CommandHandler * CommandHandler::Handle::Get() { // Not safe to work with CommandHandler in parallel with other Matter work. assertChipStackLockedByCurrentThread(); - return (mMagic == InteractionModelEngine::GetInstance()->GetMagicNumber()) ? mpHandler : nullptr; + return mpHandler; } void CommandHandler::Handle::Release() { if (mpHandler != nullptr) { - if (mMagic == InteractionModelEngine::GetInstance()->GetMagicNumber()) - { - mpHandler->DecrementHoldOff(); - } - mpHandler = nullptr; - mMagic = 0; + mpHandler->DecrementHoldOff(this); + Invalidate(); } } -CommandHandler::Handle::Handle(CommandHandler * handle) +CommandHandler::Handle::Handle(CommandHandler * handler) { - if (handle != nullptr) - { - handle->IncrementHoldOff(); - mpHandler = handle; - mMagic = InteractionModelEngine::GetInstance()->GetMagicNumber(); - } + Init(handler); } CHIP_ERROR CommandHandler::FinalizeInvokeResponseMessageAndPrepareNext() diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h index 2eed73daccdda9..cce19879a6c8a9 100644 --- a/src/app/CommandHandler.h +++ b/src/app/CommandHandler.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -110,29 +111,26 @@ class CommandHandler * The Invoke Response will not be sent until all outstanding Handles have * been destroyed or have had Release called. */ - class Handle + class Handle : public IntrusiveListNodeBase<> { public: Handle() {} Handle(const Handle & handle) = delete; Handle(Handle && handle) { - mpHandler = handle.mpHandler; - mMagic = handle.mMagic; - handle.mpHandler = nullptr; - handle.mMagic = 0; + Init(handle.mpHandler); + handle.Release(); } Handle(decltype(nullptr)) {} - Handle(CommandHandler * handle); + Handle(CommandHandler * handler); ~Handle() { Release(); } Handle & operator=(Handle && handle) { Release(); - mpHandler = handle.mpHandler; - mMagic = handle.mMagic; - handle.mpHandler = nullptr; - handle.mMagic = 0; + Init(handle.mpHandler); + + handle.Release(); return *this; } @@ -143,16 +141,19 @@ class CommandHandler } /** - * Get the CommandHandler object it holds. Get() may return a nullptr if the CommandHandler object is holds is no longer + * Get the CommandHandler object it holds. Get() may return a nullptr if the CommandHandler object it holds is no longer * valid. */ CommandHandler * Get(); void Release(); + void Invalidate() { mpHandler = nullptr; } + private: + void Init(CommandHandler * handler); + CommandHandler * mpHandler = nullptr; - uint32_t mMagic = 0; }; // Previously we kept adding arguments with default values individually as parameters. This is because there @@ -191,6 +192,14 @@ class CommandHandler */ CommandHandler(Callback * apCallback); + /* + * Destructor. + * + * The call will also invalidate all Handles created for this CommandHandler. + * + */ + ~CommandHandler(); + /* * Constructor to override the number of supported paths per invoke and command responder. * @@ -525,13 +534,13 @@ class CommandHandler * Users should use CommandHandler::Handle for management the lifespan of the CommandHandler. * DefRef should be released in reasonable time, and Close() should only be called when the refcount reached 0. */ - void IncrementHoldOff(); + void IncrementHoldOff(Handle * apHandle); /** * DecrementHoldOff is used by CommandHandler::Handle for decreasing the refcount of the CommandHandler. * When refcount reached 0, CommandHandler will send the response to the peer and shutdown. */ - void DecrementHoldOff(); + void DecrementHoldOff(Handle * apHandle); /* * Allocates a packet buffer used for encoding an invoke response payload. @@ -672,12 +681,20 @@ class CommandHandler size_t MaxPathsPerInvoke() const { return mMaxPathsPerInvoke; } + void AddToHandleList(Handle * handle); + + void RemoveFromHandleList(Handle * handle); + + void InvalidateHandles(); + bool TestOnlyIsInIdleState() const { return mState == State::Idle; } Callback * mpCallback = nullptr; InvokeResponseMessage::Builder mInvokeResponseBuilder; TLV::TLVType mDataElementContainerType = TLV::kTLVType_NotSpecified; size_t mPendingWork = 0; + /* List to store all currently-outstanding Handles for this Command Handler.*/ + IntrusiveList mpHandleList; chip::System::PacketBufferTLVWriter mCommandMessageWriter; TLV::TLVWriter mBackupWriter; diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 64c06f92354f48..97528768cb2561 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -85,7 +85,6 @@ CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeM ReturnErrorOnFailure(mpExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id, this)); mReportingEngine.Init(); - mMagic++; StatusIB::RegisterErrorFormatter(); @@ -111,9 +110,6 @@ void InteractionModelEngine::Shutdown() mCommandHandlerList = nullptr; - // Increase magic number to invalidate all Handle-s. - mMagic++; - mCommandResponderObjs.ReleaseAll(); mTimedHandlers.ForEachActiveObject([this](TimedHandler * obj) -> Loop { diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index baf02c6af73d1c..87c497c9e9955d 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -192,11 +192,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, */ WriteHandler * ActiveWriteHandlerAt(unsigned int aIndex); - /** - * The Magic number of this InteractionModelEngine, the magic number is set during Init() - */ - uint32_t GetMagicNumber() const { return mMagic; } - reporting::Engine & GetReportingEngine() { return mReportingEngine; } reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; } @@ -706,10 +701,6 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, CASESessionManager * mpCASESessionMgr = nullptr; SubscriptionResumptionStorage * mpSubscriptionResumptionStorage = nullptr; - - // A magic number for tracking values between stack Shutdown()-s and Init()-s. - // An ObjectHandle is valid iff. its magic equals to this one. - uint32_t mMagic = 0; }; } // namespace app From 7585d7162110e6117ce920914d914e50ac822320 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 7 May 2024 16:46:44 -0400 Subject: [PATCH 11/39] Add some unit tests for ExchangeContext and ExchangeMessageDispatch. (#33340) * Add some unit tests for ExchangeContext and ExchangeMessageDispatch. * Address review comment. --- src/messaging/tests/BUILD.gn | 2 +- src/messaging/tests/TestExchange.cpp | 261 +++++++++++++++++++++++++++ 2 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 src/messaging/tests/TestExchange.cpp diff --git a/src/messaging/tests/BUILD.gn b/src/messaging/tests/BUILD.gn index c597c36055754a..0e56444ba40952 100644 --- a/src/messaging/tests/BUILD.gn +++ b/src/messaging/tests/BUILD.gn @@ -49,7 +49,7 @@ static_library("helpers") { chip_test_suite_using_nltest("tests") { output_name = "libMessagingLayerTests" - test_sources = [] + test_sources = [ "TestExchange.cpp" ] if (chip_device_platform != "efr32") { # TODO(#10447): ReliableMessage Test has HF, and ExchangeMgr hangs on EFR32. diff --git a/src/messaging/tests/TestExchange.cpp b/src/messaging/tests/TestExchange.cpp new file mode 100644 index 00000000000000..67b9ab6d16d0d3 --- /dev/null +++ b/src/messaging/tests/TestExchange.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#if CHIP_CRYPTO_PSA +#include "psa/crypto.h" +#endif + +namespace { + +using namespace chip; +using namespace chip::Inet; +using namespace chip::Transport; +using namespace chip::Messaging; + +struct TestContext : Test::LoopbackMessagingContext +{ + // TODO Add TearDown function when changing test framework to Pigweed to make it more clear how it works. + // Currently, the TearDown function is from LoopbackMessagingContext + void SetUp() override + { +#if CHIP_CRYPTO_PSA + // TODO: use ASSERT_EQ, once transition to pw_unit_test is complete + VerifyOrDie(psa_crypto_init() == PSA_SUCCESS); +#endif + chip::Test::LoopbackMessagingContext::SetUp(); + } +}; + +enum : uint8_t +{ + kMsgType_TEST1 = 0xf0, + kMsgType_TEST2 = 0xf1, +}; + +class MockExchangeDelegate : public UnsolicitedMessageHandler, public ExchangeDelegate +{ +public: + CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override + { + newDelegate = this; + return CHIP_NO_ERROR; + } + + CHIP_ERROR OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && buffer) override + { + ++mReceivedMessageCount; + if (mKeepExchangeAliveOnMessageReceipt) + { + ec->WillSendMessage(); + mExchange = ec; + } + else + { + // Exchange will be closing, so don't hold on to a reference to it. + mExchange = nullptr; + } + return CHIP_NO_ERROR; + } + + void OnResponseTimeout(ExchangeContext * ec) override {} + + ExchangeMessageDispatch & GetMessageDispatch() override + { + if (mMessageDispatch != nullptr) + { + return *mMessageDispatch; + } + + return ExchangeDelegate::GetMessageDispatch(); + } + + uint32_t mReceivedMessageCount = 0; + bool mKeepExchangeAliveOnMessageReceipt = true; + ExchangeContext * mExchange = nullptr; + ExchangeMessageDispatch * mMessageDispatch = nullptr; +}; + +// Helper used by several tests. Registers delegate2 as an unsolicited message +// handler, sends a message of type requestMessageType via an exchange that has +// delegate1 as delegate, responds with responseMessageType. +template +void DoRoundTripTest(nlTestSuite * inSuite, void * inContext, MockExchangeDelegate & delegate1, MockExchangeDelegate & delegate2, + uint8_t requestMessageType, uint8_t responseMessageType, AfterRequestChecker && afterRequestChecker, + AfterResponseChecker && afterResponseChecker) +{ + TestContext & ctx = *reinterpret_cast(inContext); + + ExchangeContext * ec1 = ctx.NewExchangeToBob(&delegate1); + NL_TEST_ASSERT(inSuite, ec1 != nullptr); + + CHIP_ERROR err = ctx.GetExchangeManager().RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::Id, + requestMessageType, &delegate2); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + // To simplify things, skip MRP for all our messages, and make sure we are + // always expecting responses. + constexpr auto sendFlags = + SendFlags(Messaging::SendMessageFlags::kNoAutoRequestAck, Messaging::SendMessageFlags::kExpectResponse); + + err = ec1->SendMessage(Protocols::SecureChannel::Id, requestMessageType, + System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize), sendFlags); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DrainAndServiceIO(); + + afterRequestChecker(); + + ExchangeContext * ec2 = delegate2.mExchange; + err = ec2->SendMessage(Protocols::SecureChannel::Id, responseMessageType, + System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize), sendFlags); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + + ctx.DrainAndServiceIO(); + + afterResponseChecker(); + + ec1->Close(); + ec2->Close(); + + err = ctx.GetExchangeManager().UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::Id, kMsgType_TEST1); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); +} + +void CheckBasicMessageRoundTrip(nlTestSuite * inSuite, void * inContext) +{ + MockExchangeDelegate delegate1; + MockExchangeDelegate delegate2; + DoRoundTripTest( + inSuite, inContext, delegate1, delegate2, kMsgType_TEST1, kMsgType_TEST2, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 0); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 1); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }); +} + +void CheckBasicExchangeMessageDispatch(nlTestSuite * inSuite, void * inContext) +{ + class MockMessageDispatch : public ExchangeMessageDispatch + { + bool MessagePermitted(Protocols::Id protocol, uint8_t type) override + { + // Only allow TEST1 messages. + return protocol == Protocols::SecureChannel::Id && type == kMsgType_TEST1; + } + }; + + MockMessageDispatch dispatch; + + { + // Allowed response. + MockExchangeDelegate delegate1; + delegate1.mMessageDispatch = &dispatch; + MockExchangeDelegate delegate2; + + DoRoundTripTest( + inSuite, inContext, delegate1, delegate2, kMsgType_TEST1, kMsgType_TEST1, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 0); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 1); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }); + } + + { + // Disallowed response. + MockExchangeDelegate delegate1; + delegate1.mMessageDispatch = &dispatch; + MockExchangeDelegate delegate2; + + DoRoundTripTest( + inSuite, inContext, delegate1, delegate2, kMsgType_TEST1, kMsgType_TEST2, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 0); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }, + [&] { + NL_TEST_ASSERT(inSuite, delegate1.mReceivedMessageCount == 0); + NL_TEST_ASSERT(inSuite, delegate2.mReceivedMessageCount == 1); + }); + } +} + +// Test Suite + +/** + * Test Suite that lists all the test functions. + */ +// clang-format off +const nlTest sTests[] = +{ + NL_TEST_DEF("Test ExchangeContext::SendMessage", CheckBasicMessageRoundTrip), + NL_TEST_DEF("Test ExchangeMessageDispatch", CheckBasicExchangeMessageDispatch), + + NL_TEST_SENTINEL() +}; +// clang-format on + +// clang-format off +nlTestSuite sSuite = +{ + "Test-Exchange", + &sTests[0], + TestContext::nlTestSetUpTestSuite, + TestContext::nlTestTearDownTestSuite, + TestContext::nlTestSetUp, + TestContext::nlTestTearDown, +}; +// clang-format on + +} // namespace + +/** + * Main + */ +int TestExchange() +{ + return chip::ExecuteTestsWithContext(&sSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestExchange); From 5078a9309d7f2dda7d30460c5c5598ce48bd76ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Tue, 7 May 2024 22:59:57 +0200 Subject: [PATCH 12/39] [mrp] Make sure not all packet buffers are used for retransmissions (#33334) On constrained devices, the number of available packet buffers can be very low. During stress testing a device that has 8 buffers available, which is the default on many platforms, it was observed that the device would receive a lot of parallel read requests and then it would use all its buffers for responses. The responses would then be stored in the retransmission table, awaiting an ACK, but the ACK would never arrive because of lack of available buffers. Configure the retransmission table size to be less than the number of packet buffers to make sure that not all buffers are held by the retransmission entries, in which case the device is unable to receive an ACK and hence it becomes unavailable until any message times out. Signed-off-by: Damian Krolik --- src/messaging/ReliableMessageProtocolConfig.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/messaging/ReliableMessageProtocolConfig.h b/src/messaging/ReliableMessageProtocolConfig.h index 69135aa378de41..3dce56b9e98f56 100644 --- a/src/messaging/ReliableMessageProtocolConfig.h +++ b/src/messaging/ReliableMessageProtocolConfig.h @@ -130,7 +130,10 @@ namespace chip { #if CHIP_SYSTEM_CONFIG_USE_LWIP #if !LWIP_PBUF_FROM_CUSTOM_POOLS && PBUF_POOL_SIZE != 0 -#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE std::min(PBUF_POOL_SIZE, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS) +// Configure the table size to be less than the number of packet buffers to make sure +// that not all buffers are held by the retransmission entries, in which case the device +// is unable to receive an ACK and hence becomes unavailable until a message times out. +#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE std::min(PBUF_POOL_SIZE - 1, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS) #else #define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS #endif // !LWIP_PBUF_FROM_CUSTOM_POOLS && PBUF_POOL_SIZE != 0 @@ -138,7 +141,11 @@ namespace chip { #else // CHIP_SYSTEM_CONFIG_USE_LWIP #if CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0 -#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE std::min(CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS) +// Configure the table size to be less than the number of packet buffers to make sure +// that not all buffers are held by the retransmission entries, in which case the device +// is unable to receive an ACK and hence becomes unavailable until a message times out. +#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE \ + std::min(CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE - 1, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS) #else #define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS #endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0 From ab22a0191311b59cc8bcfbfdffe5b384021d3994 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Wed, 8 May 2024 11:05:06 +1200 Subject: [PATCH 13/39] Darwin Tests: Add missing os/lock.h import (#33349) --- src/darwin/Framework/CHIPTests/MTRAsyncWorkQueueTests.m | 1 + 1 file changed, 1 insertion(+) diff --git a/src/darwin/Framework/CHIPTests/MTRAsyncWorkQueueTests.m b/src/darwin/Framework/CHIPTests/MTRAsyncWorkQueueTests.m index 3207a851b2e9ac..aff2715971efba 100644 --- a/src/darwin/Framework/CHIPTests/MTRAsyncWorkQueueTests.m +++ b/src/darwin/Framework/CHIPTests/MTRAsyncWorkQueueTests.m @@ -16,6 +16,7 @@ #import #import +#import #import "MTRAsyncWorkQueue.h" From e887e589999a535108ced81dc73859fe8ab371bb Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Tue, 7 May 2024 23:06:18 -0700 Subject: [PATCH 14/39] [Chip-tool] Not register LIT at default (#33262) * [Chip-tool]Not register LIT at default * Restyled by autopep8 * fix test * Update test_definition.py * Update test_definition.py * Update test_definition.py * address comments * Update PairingCommand.cpp * Update examples/chip-tool/commands/pairing/PairingCommand.h Co-authored-by: Boris Zbarsky * Update scripts/tests/chiptest/test_definition.py Co-authored-by: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> * make icd-registration happen with lit only * disable lit test in darwin framework tool * address comment --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky Co-authored-by: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> --- examples/chip-tool/commands/pairing/PairingCommand.cpp | 2 +- examples/chip-tool/commands/pairing/PairingCommand.h | 6 +++--- scripts/tests/chiptest/test_definition.py | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index 31da1329308c5b..5f6c179779f3c2 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -136,7 +136,7 @@ CommissioningParameters PairingCommand::GetCommissioningParameters() params.SetDSTOffsets(mDSTOffsetList); } - if (!mSkipICDRegistration.ValueOr(false)) + if (mICDRegistration.ValueOr(false)) { params.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete); diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 4df17f7dee40b5..99b0fd0c91882e 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -65,8 +65,8 @@ class PairingCommand : public CHIPCommand, "Bypass the attestation verifier. If not provided or false, the attestation verifier is not bypassed." " If true, the commissioning will continue in case of attestation verification failure."); AddArgument("case-auth-tags", 1, UINT32_MAX, &mCASEAuthTags, "The CATs to be encoded in the NOC sent to the commissionee"); - AddArgument("skip-icd-registration", 0, 1, &mSkipICDRegistration, - "Skip registering for check-ins from ICDs during commissioning. Default: false"); + AddArgument("icd-registration", 0, 1, &mICDRegistration, + "Whether to register for check-ins from ICDs during commissioning. Default: false"); AddArgument("icd-check-in-nodeid", 0, UINT64_MAX, &mICDCheckInNodeId, "The check-in node id for the ICD, default: node id of the commissioner."); AddArgument("icd-monitored-subject", 0, UINT64_MAX, &mICDMonitoredSubject, @@ -233,7 +233,7 @@ class PairingCommand : public CHIPCommand, chip::Optional mBypassAttestationVerifier; chip::Optional> mCASEAuthTags; chip::Optional mCountryCode; - chip::Optional mSkipICDRegistration; + chip::Optional mICDRegistration; chip::Optional mICDCheckInNodeId; chip::Optional mICDSymmetricKey; chip::Optional mICDMonitoredSubject; diff --git a/scripts/tests/chiptest/test_definition.py b/scripts/tests/chiptest/test_definition.py index 12c59cfad0cc41..970c098f1354bb 100644 --- a/scripts/tests/chiptest/test_definition.py +++ b/scripts/tests/chiptest/test_definition.py @@ -373,6 +373,8 @@ def Run(self, runner, apps_register, paths: ApplicationPaths, pics_file: str, dependencies=[apps_register], timeout_seconds=timeout_seconds) else: pairing_cmd = paths.chip_tool_with_python_cmd + ['pairing', 'code', TEST_NODE_ID, setupCode] + if self.target == TestTarget.LIT_ICD and test_runtime == TestRunTime.CHIP_TOOL_PYTHON: + pairing_cmd += ['--icd-registration', 'true'] test_cmd = paths.chip_tool_with_python_cmd + ['tests', self.run_name] + ['--PICS', pics_file] server_args = ['--server_path', paths.chip_tool[-1]] + \ ['--server_arguments', 'interactive server' + From 7be4e8bc5014a6b83e11f028a911032d85e18e04 Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Wed, 8 May 2024 07:01:44 -0700 Subject: [PATCH 15/39] Darwin: promote `BooleanStateConfiguration` from Provisional to Introduced (#33323) * Darwin: promote `BooleanStateConfiguration` to Introduced (YAML step) * Darwin: promote `BooleanStateConfiguration` to Introduced (codegen step) --- .../CHIP/templates/availability.yaml | 47 ++++++++ .../CHIP/zap-generated/MTRBaseClusters.h | 110 +++++++++--------- .../CHIP/zap-generated/MTRClusterConstants.h | 36 +++--- .../CHIP/zap-generated/MTRClusters.h | 38 +++--- .../zap-generated/MTRCommandPayloadsObjc.h | 8 +- .../CHIP/zap-generated/MTRStructsObjc.h | 10 +- .../zap-generated/cluster/Commands.h | 85 -------------- 7 files changed, 148 insertions(+), 186 deletions(-) diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index e5cca2e7f47352..e4c27029b43ea0 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -8515,6 +8515,7 @@ clusters: - ActivatedCarbonFilterMonitoring - AirQuality + - BooleanStateConfiguration - ElectricalEnergyMeasurement - ElectricalPowerMeasurement - HEPAFilterMonitoring @@ -8550,6 +8551,20 @@ - AttributeList - FeatureMap - ClusterRevision + BooleanStateConfiguration: + - CurrentSensitivityLevel + - SupportedSensitivityLevels + - DefaultSensitivityLevel + - AlarmsActive + - AlarmsSuppressed + - AlarmsEnabled + - AlarmsSupported + - SensorFault + - GeneratedCommandList + - AcceptedCommandList + - AttributeList + - FeatureMap + - ClusterRevision ElectricalEnergyMeasurement: - Accuracy - CumulativeEnergyImported @@ -8791,6 +8806,9 @@ - FeatureMap - ClusterRevision commands: + BooleanStateConfiguration: + - SuppressAlarm + - EnableDisableAlarm ActivatedCarbonFilterMonitoring: - ResetCondition FanControl: @@ -8800,6 +8818,11 @@ SmokeCOAlarm: - SelfTestRequest command fields: + BooleanStateConfiguration: + SuppressAlarm: + - alarmsToSuppress + EnableDisableAlarm: + - alarmsToEnableDisable FanControl: Step: - direction @@ -8887,6 +8910,9 @@ - productIdentifierType - productIdentifierValue events: + BooleanStateConfiguration: + - AlarmsStateChanged + - SensorFault ElectricalEnergyMeasurement: - CumulativeEnergyMeasured - PeriodicEnergyMeasured @@ -8905,6 +8931,12 @@ - InterconnectCOAlarm - AllClear event fields: + BooleanStateConfiguration: + AlarmsStateChanged: + - alarmsActive + - alarmsSuppressed + SensorFault: + - sensorFault ElectricalEnergyMeasurement: CumulativeEnergyMeasured: - energyImported @@ -9292,6 +9324,10 @@ - Feature AirQuality: - Feature + BooleanStateConfiguration: + - Feature + - AlarmModeBitmap + - SensorFaultBitmap ElectricalEnergyMeasurement: - Feature ElectricalPowerMeasurement: @@ -9332,6 +9368,17 @@ - Moderate - VeryPoor - ExtremelyPoor + BooleanStateConfiguration: + Feature: + - Visual + - Audible + - AlarmSuppress + - SensitivityLevel + AlarmModeBitmap: + - Visual + - Audible + SensorFaultBitmap: + - GeneralFault ElectricalEnergyMeasurement: Feature: - ImportedEnergy diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 4ba691a2f509ac..9635e226e522cd 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -6963,7 +6963,7 @@ MTR_NEWLY_AVAILABLE * * This cluster is used to configure a boolean sensor. */ -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBaseClusterBooleanStateConfiguration : MTRGenericBaseCluster /** @@ -6971,75 +6971,75 @@ MTR_PROVISIONALLY_AVAILABLE * * This command is used to suppress the specified alarm mode. */ -- (void)suppressAlarmWithParams:(MTRBooleanStateConfigurationClusterSuppressAlarmParams *)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)suppressAlarmWithParams:(MTRBooleanStateConfigurationClusterSuppressAlarmParams *)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; /** * Command EnableDisableAlarm * * This command is used to enable or disable the specified alarm mode. */ -- (void)enableDisableAlarmWithParams:(MTRBooleanStateConfigurationClusterEnableDisableAlarmParams *)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)enableDisableAlarmWithParams:(MTRBooleanStateConfigurationClusterEnableDisableAlarmParams *)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeCurrentSensitivityLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSNumber * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeCurrentSensitivityLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSNumber * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeCurrentSensitivityLevelWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeCurrentSensitivityLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeCurrentSensitivityLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeSupportedSensitivityLevelsWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeSupportedSensitivityLevelsWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeSupportedSensitivityLevelsWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeSupportedSensitivityLevelsWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeSupportedSensitivityLevelsWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeDefaultSensitivityLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeDefaultSensitivityLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeDefaultSensitivityLevelWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeDefaultSensitivityLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeDefaultSensitivityLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAlarmsActiveWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAlarmsActiveWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAlarmsActiveWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAlarmsActiveWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAlarmsActiveWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAlarmsSuppressedWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAlarmsSuppressedWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAlarmsSuppressedWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAlarmsSuppressedWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAlarmsSuppressedWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAlarmsEnabledWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAlarmsEnabledWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAlarmsEnabledWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAlarmsEnabledWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAlarmsEnabledWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAlarmsSupportedWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAlarmsSupportedWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAlarmsSupportedWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAlarmsSupportedWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAlarmsSupportedWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeSensorFaultWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeSensorFaultWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeSensorFaultWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeSensorFaultWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeSensorFaultWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams *)params @@ -7047,23 +7047,23 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -7078,7 +7078,7 @@ MTR_PROVISIONALLY_AVAILABLE */ - (instancetype _Nullable)initWithDevice:(MTRBaseDevice *)device endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE; @end @@ -17699,20 +17699,20 @@ typedef NS_OPTIONS(uint32_t, MTRActivatedCarbonFilterMonitoringFeature) { } MTR_NEWLY_AVAILABLE; typedef NS_OPTIONS(uint8_t, MTRBooleanStateConfigurationAlarmModeBitmap) { - MTRBooleanStateConfigurationAlarmModeBitmapVisual MTR_PROVISIONALLY_AVAILABLE = 0x1, - MTRBooleanStateConfigurationAlarmModeBitmapAudible MTR_PROVISIONALLY_AVAILABLE = 0x2, -} MTR_PROVISIONALLY_AVAILABLE; + MTRBooleanStateConfigurationAlarmModeBitmapVisual MTR_NEWLY_AVAILABLE = 0x1, + MTRBooleanStateConfigurationAlarmModeBitmapAudible MTR_NEWLY_AVAILABLE = 0x2, +} MTR_NEWLY_AVAILABLE; typedef NS_OPTIONS(uint32_t, MTRBooleanStateConfigurationFeature) { - MTRBooleanStateConfigurationFeatureVisual MTR_PROVISIONALLY_AVAILABLE = 0x1, - MTRBooleanStateConfigurationFeatureAudible MTR_PROVISIONALLY_AVAILABLE = 0x2, - MTRBooleanStateConfigurationFeatureAlarmSuppress MTR_PROVISIONALLY_AVAILABLE = 0x4, - MTRBooleanStateConfigurationFeatureSensitivityLevel MTR_PROVISIONALLY_AVAILABLE = 0x8, -} MTR_PROVISIONALLY_AVAILABLE; + MTRBooleanStateConfigurationFeatureVisual MTR_NEWLY_AVAILABLE = 0x1, + MTRBooleanStateConfigurationFeatureAudible MTR_NEWLY_AVAILABLE = 0x2, + MTRBooleanStateConfigurationFeatureAlarmSuppress MTR_NEWLY_AVAILABLE = 0x4, + MTRBooleanStateConfigurationFeatureSensitivityLevel MTR_NEWLY_AVAILABLE = 0x8, +} MTR_NEWLY_AVAILABLE; typedef NS_OPTIONS(uint16_t, MTRBooleanStateConfigurationSensorFaultBitmap) { - MTRBooleanStateConfigurationSensorFaultBitmapGeneralFault MTR_PROVISIONALLY_AVAILABLE = 0x1, -} MTR_PROVISIONALLY_AVAILABLE; + MTRBooleanStateConfigurationSensorFaultBitmapGeneralFault MTR_NEWLY_AVAILABLE = 0x1, +} MTR_NEWLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRValveConfigurationAndControlStatusCode) { MTRValveConfigurationAndControlStatusCodeFailureDueToFault MTR_PROVISIONALLY_AVAILABLE = 0x02, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 3d7ea40fef43ee..5dd4cabe0fef0e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -147,7 +147,7 @@ typedef NS_ENUM(uint32_t, MTRClusterIDType) { MTRClusterIDTypeScenesManagementID MTR_PROVISIONALLY_AVAILABLE = 0x00000062, MTRClusterIDTypeHEPAFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000071, MTRClusterIDTypeActivatedCarbonFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000072, - MTRClusterIDTypeBooleanStateConfigurationID MTR_PROVISIONALLY_AVAILABLE = 0x00000080, + MTRClusterIDTypeBooleanStateConfigurationID MTR_NEWLY_AVAILABLE = 0x00000080, MTRClusterIDTypeValveConfigurationAndControlID MTR_PROVISIONALLY_AVAILABLE = 0x00000081, MTRClusterIDTypeElectricalPowerMeasurementID MTR_NEWLY_AVAILABLE = 0x00000090, MTRClusterIDTypeElectricalEnergyMeasurementID MTR_NEWLY_AVAILABLE = 0x00000091, @@ -2545,20 +2545,20 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterActivatedCarbonFilterMonitoringAttributeClusterRevisionID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, // Cluster BooleanStateConfiguration attributes - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeCurrentSensitivityLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeSupportedSensitivityLevelsID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeDefaultSensitivityLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000002, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsActiveID MTR_PROVISIONALLY_AVAILABLE = 0x00000003, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsSuppressedID MTR_PROVISIONALLY_AVAILABLE = 0x00000004, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000005, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsSupportedID MTR_PROVISIONALLY_AVAILABLE = 0x00000006, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeSensorFaultID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeCurrentSensitivityLevelID MTR_NEWLY_AVAILABLE = 0x00000000, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeSupportedSensitivityLevelsID MTR_NEWLY_AVAILABLE = 0x00000001, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeDefaultSensitivityLevelID MTR_NEWLY_AVAILABLE = 0x00000002, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsActiveID MTR_NEWLY_AVAILABLE = 0x00000003, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsSuppressedID MTR_NEWLY_AVAILABLE = 0x00000004, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsEnabledID MTR_NEWLY_AVAILABLE = 0x00000005, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAlarmsSupportedID MTR_NEWLY_AVAILABLE = 0x00000006, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeSensorFaultID MTR_NEWLY_AVAILABLE = 0x00000007, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeGeneratedCommandListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAcceptedCommandListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAttributeListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeFeatureMapID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, - MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeClusterRevisionID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeAttributeListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeFeatureMapID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, + MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeClusterRevisionID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, // Cluster ValveConfigurationAndControl attributes MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeOpenDurationID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, @@ -6266,8 +6266,8 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterActivatedCarbonFilterMonitoringCommandResetConditionID MTR_NEWLY_AVAILABLE = 0x00000000, // Cluster BooleanStateConfiguration commands - MTRCommandIDTypeClusterBooleanStateConfigurationCommandSuppressAlarmID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTRCommandIDTypeClusterBooleanStateConfigurationCommandEnableDisableAlarmID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTRCommandIDTypeClusterBooleanStateConfigurationCommandSuppressAlarmID MTR_NEWLY_AVAILABLE = 0x00000000, + MTRCommandIDTypeClusterBooleanStateConfigurationCommandEnableDisableAlarmID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster ValveConfigurationAndControl commands MTRCommandIDTypeClusterValveConfigurationAndControlCommandOpenID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, @@ -7191,8 +7191,8 @@ typedef NS_ENUM(uint32_t, MTREventIDType) { MTREventIDTypeClusterRVCOperationalStateEventOperationCompletionID MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4)) = 0x00000001, // Cluster BooleanStateConfiguration events - MTREventIDTypeClusterBooleanStateConfigurationEventAlarmsStateChangedID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTREventIDTypeClusterBooleanStateConfigurationEventSensorFaultID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTREventIDTypeClusterBooleanStateConfigurationEventAlarmsStateChangedID MTR_NEWLY_AVAILABLE = 0x00000000, + MTREventIDTypeClusterBooleanStateConfigurationEventSensorFaultID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster ValveConfigurationAndControl events MTREventIDTypeClusterValveConfigurationAndControlEventValveStateChangedID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index a3b2e0f35598ab..d6689c33b1766e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -3306,41 +3306,41 @@ MTR_NEWLY_AVAILABLE * Cluster Boolean State Configuration * This cluster is used to configure a boolean sensor. */ -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRClusterBooleanStateConfiguration : MTRGenericCluster -- (void)suppressAlarmWithParams:(MTRBooleanStateConfigurationClusterSuppressAlarmParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)enableDisableAlarmWithParams:(MTRBooleanStateConfigurationClusterEnableDisableAlarmParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)suppressAlarmWithParams:(MTRBooleanStateConfigurationClusterSuppressAlarmParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; +- (void)enableDisableAlarmWithParams:(MTRBooleanStateConfigurationClusterEnableDisableAlarmParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeCurrentSensitivityLevelWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeCurrentSensitivityLevelWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; +- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_NEWLY_AVAILABLE; +- (void)writeAttributeCurrentSensitivityLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeSupportedSensitivityLevelsWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeSupportedSensitivityLevelsWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeDefaultSensitivityLevelWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeDefaultSensitivityLevelWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAlarmsActiveWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAlarmsActiveWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAlarmsSuppressedWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAlarmsSuppressedWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAlarmsEnabledWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAlarmsEnabledWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAlarmsSupportedWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAlarmsSupportedWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeSensorFaultWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeSensorFaultWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -3355,7 +3355,7 @@ MTR_PROVISIONALLY_AVAILABLE */ - (instancetype _Nullable)initWithDevice:(MTRDevice *)device endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE; @end diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 4e774a8cb54e38..a1d6600c95ed09 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -5240,10 +5240,10 @@ MTR_NEWLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBooleanStateConfigurationClusterSuppressAlarmParams : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull alarmsToSuppress MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull alarmsToSuppress MTR_NEWLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5270,10 +5270,10 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBooleanStateConfigurationClusterEnableDisableAlarmParams : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull alarmsToEnableDisable MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull alarmsToEnableDisable MTR_NEWLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index a311e59ce46b16..a29154cd4b5d23 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -1049,15 +1049,15 @@ MTR_NEWLY_AVAILABLE @property (nonatomic, copy) NSString * _Nonnull productIdentifierValue MTR_NEWLY_AVAILABLE; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBooleanStateConfigurationClusterAlarmsStateChangedEvent : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull alarmsActive MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable alarmsSuppressed MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull alarmsActive MTR_NEWLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable alarmsSuppressed MTR_NEWLY_AVAILABLE; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBooleanStateConfigurationClusterSensorFaultEvent : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull sensorFault MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull sensorFault MTR_NEWLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 5d121f59368ea5..a59a148293d29a 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -72909,7 +72909,6 @@ class SubscribeAttributeActivatedCarbonFilterMonitoringClusterRevision : public } }; -#if MTR_ENABLE_PROVISIONAL /*----------------------------------------------------------------------------*\ | Cluster BooleanStateConfiguration | 0x0080 | |------------------------------------------------------------------------------| @@ -72938,7 +72937,6 @@ class SubscribeAttributeActivatedCarbonFilterMonitoringClusterRevision : public | * SensorFault | 0x0001 | \*----------------------------------------------------------------------------*/ -#if MTR_ENABLE_PROVISIONAL /* * Command SuppressAlarm */ @@ -72947,9 +72945,7 @@ class BooleanStateConfigurationSuppressAlarm : public ClusterCommand { BooleanStateConfigurationSuppressAlarm() : ClusterCommand("suppress-alarm") { -#if MTR_ENABLE_PROVISIONAL AddArgument("AlarmsToSuppress", 0, UINT8_MAX, &mRequest.alarmsToSuppress); -#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -72964,9 +72960,7 @@ class BooleanStateConfigurationSuppressAlarm : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterBooleanStateConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRBooleanStateConfigurationClusterSuppressAlarmParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; -#if MTR_ENABLE_PROVISIONAL params.alarmsToSuppress = [NSNumber numberWithUnsignedChar:mRequest.alarmsToSuppress.Raw()]; -#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -72990,8 +72984,6 @@ class BooleanStateConfigurationSuppressAlarm : public ClusterCommand { chip::app::Clusters::BooleanStateConfiguration::Commands::SuppressAlarm::Type mRequest; }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL /* * Command EnableDisableAlarm */ @@ -73000,9 +72992,7 @@ class BooleanStateConfigurationEnableDisableAlarm : public ClusterCommand { BooleanStateConfigurationEnableDisableAlarm() : ClusterCommand("enable-disable-alarm") { -#if MTR_ENABLE_PROVISIONAL AddArgument("AlarmsToEnableDisable", 0, UINT8_MAX, &mRequest.alarmsToEnableDisable); -#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -73017,9 +73007,7 @@ class BooleanStateConfigurationEnableDisableAlarm : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterBooleanStateConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRBooleanStateConfigurationClusterEnableDisableAlarmParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; -#if MTR_ENABLE_PROVISIONAL params.alarmsToEnableDisable = [NSNumber numberWithUnsignedChar:mRequest.alarmsToEnableDisable.Raw()]; -#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -73043,10 +73031,6 @@ class BooleanStateConfigurationEnableDisableAlarm : public ClusterCommand { chip::app::Clusters::BooleanStateConfiguration::Commands::EnableDisableAlarm::Type mRequest; }; -#endif // MTR_ENABLE_PROVISIONAL - -#if MTR_ENABLE_PROVISIONAL - /* * Attribute CurrentSensitivityLevel */ @@ -73170,9 +73154,6 @@ class SubscribeAttributeBooleanStateConfigurationCurrentSensitivityLevel : publi } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute SupportedSensitivityLevels */ @@ -73255,9 +73236,6 @@ class SubscribeAttributeBooleanStateConfigurationSupportedSensitivityLevels : pu } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute DefaultSensitivityLevel */ @@ -73340,9 +73318,6 @@ class SubscribeAttributeBooleanStateConfigurationDefaultSensitivityLevel : publi } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AlarmsActive */ @@ -73425,9 +73400,6 @@ class SubscribeAttributeBooleanStateConfigurationAlarmsActive : public Subscribe } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AlarmsSuppressed */ @@ -73510,9 +73482,6 @@ class SubscribeAttributeBooleanStateConfigurationAlarmsSuppressed : public Subsc } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AlarmsEnabled */ @@ -73595,9 +73564,6 @@ class SubscribeAttributeBooleanStateConfigurationAlarmsEnabled : public Subscrib } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AlarmsSupported */ @@ -73680,9 +73646,6 @@ class SubscribeAttributeBooleanStateConfigurationAlarmsSupported : public Subscr } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute SensorFault */ @@ -73765,9 +73728,6 @@ class SubscribeAttributeBooleanStateConfigurationSensorFault : public SubscribeA } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute GeneratedCommandList */ @@ -73850,9 +73810,6 @@ class SubscribeAttributeBooleanStateConfigurationGeneratedCommandList : public S } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AcceptedCommandList */ @@ -73935,7 +73892,6 @@ class SubscribeAttributeBooleanStateConfigurationAcceptedCommandList : public Su } }; -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL /* @@ -74021,7 +73977,6 @@ class SubscribeAttributeBooleanStateConfigurationEventList : public SubscribeAtt }; #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL /* * Attribute AttributeList @@ -74105,9 +74060,6 @@ class SubscribeAttributeBooleanStateConfigurationAttributeList : public Subscrib } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute FeatureMap */ @@ -74190,9 +74142,6 @@ class SubscribeAttributeBooleanStateConfigurationFeatureMap : public SubscribeAt } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute ClusterRevision */ @@ -74275,8 +74224,6 @@ class SubscribeAttributeBooleanStateConfigurationClusterRevision : public Subscr } }; -#endif // MTR_ENABLE_PROVISIONAL -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL /*----------------------------------------------------------------------------*\ | Cluster ValveConfigurationAndControl | 0x0081 | @@ -185407,85 +185354,53 @@ void registerClusterActivatedCarbonFilterMonitoring(Commands & commands) } void registerClusterBooleanStateConfiguration(Commands & commands) { -#if MTR_ENABLE_PROVISIONAL using namespace chip::app::Clusters::BooleanStateConfiguration; const char * clusterName = "BooleanStateConfiguration"; commands_list clusterCommands = { make_unique(Id), // -#if MTR_ENABLE_PROVISIONAL make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // make_unique(Id), // -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // }; commands.RegisterCluster(clusterName, clusterCommands); -#endif // MTR_ENABLE_PROVISIONAL } void registerClusterValveConfigurationAndControl(Commands & commands) { From b976e7aa01e76c23763698af6d0e6af8ce65f7db Mon Sep 17 00:00:00 2001 From: Sharad Binjola <31142146+sharadb-amazon@users.noreply.github.com> Date: Wed, 8 May 2024 07:04:34 -0700 Subject: [PATCH 16/39] iOS tv-casting-app: deprecating old casting impl, replacing with shim (#33350) --- examples/tv-casting-app/APIs.md | 4 +- .../project.pbxproj | 112 +- .../CastingServerBridge.h | 1263 ---------------- .../CommissionableDataProviderImpl.hpp | 62 - .../CommissionableDataProviderImpl.mm | 209 --- ...viceAttestationCredentialsProviderImpl.hpp | 48 - ...eviceAttestationCredentialsProviderImpl.mm | 164 --- .../MatterTvCastingBridge/MCAttribute.h | 2 - .../MatterTvCastingBridge/MCCastingPlayer.h | 2 + .../MatterTvCastingBridge/MCCastingPlayer.mm | 24 + .../MCCastingPlayerDiscovery.mm | 2 +- .../MCCastingPlayer_Internal.h | 2 + .../MCDeviceAttestationCredentialsProvider.h | 3 +- .../MCDeviceAttestationCredentialsProvider.mm | 56 +- .../MatterTvCastingBridge/MCEndpoint.h | 2 +- .../MatterTvCastingBridge/MCEndpoint.mm | 28 +- .../MCEndpoint_Internal.h | 2 + .../MatterTvCastingBridge/MCErrorUtils.h | 2 + .../MatterTvCastingBridge/MCErrorUtils.mm | 4 + .../MatterTvCastingBridge/MatterError.mm | 2 +- .../MatterTvCastingBridge.h | 6 +- .../{ => compat-shim}/AppParameters.h | 1 + .../{ => compat-shim}/AppParameters.mm | 0 .../CastingPlayerDiscoveryListenerCompat.h | 34 + .../CastingPlayerDiscoveryListenerCompat.mm | 134 ++ .../compat-shim/CastingServerBridge.h | 739 ++++++++++ .../compat-shim/CastingServerBridge.mm | 1290 +++++++++++++++++ .../CommissioningCallbackHandlers.h | 14 +- .../CommissioningCallbackHandlers.m | 6 +- .../{ => compat-shim}/ContentApp.h | 5 + .../{ => compat-shim}/ContentApp.mm | 11 + .../{ => compat-shim}/ContentLauncherTypes.h | 0 .../{ => compat-shim}/ContentLauncherTypes.mm | 0 .../DataSourceCompat.h} | 19 +- .../compat-shim/DataSourceCompat.mm | 124 ++ .../DeviceAttestationCredentialsHolder.h | 1 + .../DeviceAttestationCredentialsHolder.m | 0 .../{ => compat-shim}/DiscoveredNodeData.h | 6 + .../{ => compat-shim}/DiscoveredNodeData.mm | 39 +- .../{ => compat-shim}/MediaPlaybackTypes.h | 0 .../{ => compat-shim}/MediaPlaybackTypes.mm | 0 .../{ => compat-shim}/OnboardingPayload.h | 0 .../{ => compat-shim}/OnboardingPayload.m | 0 .../{ => compat-shim}/TargetNavigatorTypes.h | 0 .../{ => compat-shim}/TargetNavigatorTypes.mm | 0 .../{ => compat-shim}/VideoPlayer.h | 7 + .../{ => compat-shim}/VideoPlayer.m | 32 + .../MCEndpointClusterType.h | 6 +- .../TvCasting.xcodeproj/project.pbxproj | 50 +- .../TvCasting/CommissioningViewModel.swift | 118 -- .../TvCasting/TvCasting/ConnectionView.swift | 78 - .../TvCasting/ConnectionViewModel.swift | 63 - .../TvCasting/TvCasting/ContentView.swift | 2 +- ...scribeToCurrentStateExampleViewModel.swift | 5 +- .../TvCasting/StartFromCacheView.swift | 83 -- .../TvCasting/StartFromCacheViewModel.swift | 50 - .../TvCasting/TvCasting/TvCastingApp.swift | 2 +- .../TvCasting/{ => compat}/CertTestView.swift | 0 .../{ => compat}/CertTestViewModel.swift | 14 +- .../{ => compat}/ClusterSelectorView.swift | 1 + .../CommissionerDiscoveryView.swift | 14 +- .../CommissionerDiscoveryViewModel.swift | 38 +- .../{ => compat}/CommissioningView.swift | 25 +- .../compat/CommissioningViewModel.swift | 118 ++ .../{ => compat}/ContentLauncherView.swift | 1 + .../ContentLauncherViewModel.swift | 8 +- .../TvCasting/{ => compat}/ExampleDAC.swift | 0 .../{ => compat}/MediaPlaybackView.swift | 1 + .../{ => compat}/MediaPlaybackViewModel.swift | 0 .../tv-casting-common/core/CastingPlayer.cpp | 1 + .../support/CastingStore.cpp | 8 +- .../support/ChipDeviceEventHandler.cpp | 18 +- 72 files changed, 2782 insertions(+), 2383 deletions(-) delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.hpp delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.mm delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.hpp delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.mm rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/AppParameters.h (91%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/AppParameters.mm (100%) create mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.h create mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.mm create mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.h create mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.mm rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/CommissioningCallbackHandlers.h (83%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/CommissioningCallbackHandlers.m (85%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/ContentApp.h (87%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/ContentApp.mm (87%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/ContentLauncherTypes.h (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/ContentLauncherTypes.mm (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{MCObserver.h => compat-shim/DataSourceCompat.h} (54%) create mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.mm rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/DeviceAttestationCredentialsHolder.h (94%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/DeviceAttestationCredentialsHolder.m (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/DiscoveredNodeData.h (86%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/DiscoveredNodeData.mm (62%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/MediaPlaybackTypes.h (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/MediaPlaybackTypes.mm (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/OnboardingPayload.h (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/OnboardingPayload.m (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/TargetNavigatorTypes.h (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/TargetNavigatorTypes.mm (100%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/VideoPlayer.h (89%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => compat-shim}/VideoPlayer.m (70%) rename examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/{ => zap-generated}/MCEndpointClusterType.h (82%) delete mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift delete mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionView.swift delete mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionViewModel.swift delete mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheView.swift delete mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheViewModel.swift rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/CertTestView.swift (100%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/CertTestViewModel.swift (98%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/ClusterSelectorView.swift (97%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/CommissionerDiscoveryView.swift (82%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/CommissionerDiscoveryViewModel.swift (57%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/CommissioningView.swift (78%) create mode 100644 examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningViewModel.swift rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/ContentLauncherView.swift (97%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/ContentLauncherViewModel.swift (89%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/ExampleDAC.swift (100%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/MediaPlaybackView.swift (97%) rename examples/tv-casting-app/darwin/TvCasting/TvCasting/{ => compat}/MediaPlaybackViewModel.swift (100%) diff --git a/examples/tv-casting-app/APIs.md b/examples/tv-casting-app/APIs.md index 1bbb189e7179d7..76af45a2d326d4 100644 --- a/examples/tv-casting-app/APIs.md +++ b/examples/tv-casting-app/APIs.md @@ -1362,7 +1362,7 @@ if(currentStateAttribute == nil) } // call read on currentStateAttribute and pass in a completion block -currentStateAttribute!.read(nil) { context, before, after, err in +currentStateAttribute!.subscribe(nil, completion: { context, before, after, err in let dateFormatter = DateFormatter() dateFormatter.dateFormat = "HH:mm:ss" @@ -1386,7 +1386,7 @@ currentStateAttribute!.read(nil) { context, before, after, err in self.status = "Read CurrentState value: \(String(describing: after)) at \(currentTime)" } } -} +}, minInterval: 0, maxInterval: 1) ``` The Casting client can Shutdown all running Subscriptions by calling the diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj index 5b1a37207b10b0..5df8ce26bf4019 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge.xcodeproj/project.pbxproj @@ -26,8 +26,6 @@ 3C2346232B362B9500FA276E /* MCCastingPlayerDiscovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C2346222B362B9500FA276E /* MCCastingPlayerDiscovery.h */; }; 3C2346252B362BBB00FA276E /* MCCastingPlayerDiscovery.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C2346242B362BBB00FA276E /* MCCastingPlayerDiscovery.mm */; }; 3C2696FB2B4A5FC50026E771 /* MCEndpointFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C2696FA2B4A5FC50026E771 /* MCEndpointFilter.m */; }; - 3C26AC8C2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3C26AC8B2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp */; }; - 3C26AC902927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C26AC8F2927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm */; }; 3C26AC9329282B8100BA6881 /* DeviceAttestationCredentialsHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C26AC9229282B8100BA6881 /* DeviceAttestationCredentialsHolder.m */; }; 3C4AE650286A7D4D005B52A4 /* OnboardingPayload.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4AE64F286A7D4D005B52A4 /* OnboardingPayload.m */; }; 3C4E53B028E4F28100F293E8 /* MediaPlaybackTypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C4E53AF28E4F28100F293E8 /* MediaPlaybackTypes.mm */; }; @@ -47,7 +45,6 @@ 3C4F522A2B51DFAE00BB8A10 /* MCCommand_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C4F52292B51DFAE00BB8A10 /* MCCommand_Internal.h */; }; 3C4F522C2B51E02800BB8A10 /* MCCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C4F522B2B51E02800BB8A10 /* MCCommand.mm */; }; 3C621CA52B605A6A005CDBA3 /* MCAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C621CA42B605A6A005CDBA3 /* MCAttribute.h */; }; - 3C621CA72B605AA1005CDBA3 /* MCObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C621CA62B605AA1005CDBA3 /* MCObserver.h */; }; 3C621CA92B605C52005CDBA3 /* MCAttribute_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C621CA82B605C52005CDBA3 /* MCAttribute_Internal.h */; }; 3C621CAB2B605C6E005CDBA3 /* MCAttribute.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CAA2B605C6E005CDBA3 /* MCAttribute.mm */; }; 3C66FBFC290327BB00B63FE7 /* AppParameters.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C66FBFB290327BB00B63FE7 /* AppParameters.mm */; }; @@ -58,15 +55,15 @@ 3C81C75028F7A7D3001CB9D1 /* VideoPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C74F28F7A7D3001CB9D1 /* VideoPlayer.m */; }; 3C9437922B3B478E0096E5F4 /* MCErrorUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C9437912B3B478E0096E5F4 /* MCErrorUtils.h */; }; 3C9437942B3B47A10096E5F4 /* MCErrorUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C9437932B3B47A10096E5F4 /* MCErrorUtils.mm */; }; + 3C996C272BD31FEA0027BD8A /* DataSourceCompat.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C996C262BD31FEA0027BD8A /* DataSourceCompat.mm */; }; + 3C996C2B2BD6F4960027BD8A /* CastingPlayerDiscoveryListenerCompat.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C996C2A2BD6F4950027BD8A /* CastingPlayerDiscoveryListenerCompat.mm */; }; + 3CC3979E2BE9857C00465462 /* MCCastingPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3C9437882B364F5E0096E5F4 /* MCCastingPlayer.mm */; }; 3CCB87212869085400771BAD /* MatterTvCastingBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB87202869085400771BAD /* MatterTvCastingBridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3CCB8737286A555500771BAD /* libTvCastingCommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CCB8735286A555500771BAD /* libTvCastingCommon.a */; }; 3CCB873F286A593700771BAD /* DiscoveredNodeData.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB8739286A593700771BAD /* DiscoveredNodeData.mm */; }; 3CCB8740286A593700771BAD /* CastingServerBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB873A286A593700771BAD /* CastingServerBridge.h */; }; 3CCB8741286A593700771BAD /* DiscoveredNodeData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB873B286A593700771BAD /* DiscoveredNodeData.h */; }; - 3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3CCB873C286A593700771BAD /* ConversionUtils.hpp */; }; 3CCB8743286A593700771BAD /* CastingServerBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873D286A593700771BAD /* CastingServerBridge.mm */; }; - 3CCB8744286A593700771BAD /* ConversionUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CCB873E286A593700771BAD /* ConversionUtils.mm */; }; - 3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */; }; 3CD73F172A9E6884009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD73F162A9E6884009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.h */; }; 3CD73F192A9E68A7009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CD73F182A9E68A7009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.mm */; }; 3CD73F1C2A9E8396009D82D1 /* MCCommissionableDataProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD73F1B2A9E8396009D82D1 /* MCCommissionableDataProvider.h */; }; @@ -75,7 +72,6 @@ 3CD73F222A9EA078009D82D1 /* MCDeviceAttestationCredentials.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CD73F212A9EA077009D82D1 /* MCDeviceAttestationCredentials.mm */; }; 3CE5ECCE2A673B30007CF331 /* CommissioningCallbackHandlers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */; }; 3CE5ECD02A673E2C007CF331 /* CommissioningCallbackHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */; }; - 3CE868F42946D76200FCB92B /* CommissionableDataProviderImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */; }; 3CF71C0A2A992D0D003A5CE5 /* MCCastingApp.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CF71C092A992D0D003A5CE5 /* MCCastingApp.h */; }; 3CF71C0C2A992D25003A5CE5 /* MCCastingApp.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3CF71C0B2A992D25003A5CE5 /* MCCastingApp.mm */; }; 3CF71C0E2A992DA2003A5CE5 /* MCDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CF71C0D2A992DA2003A5CE5 /* MCDataSource.h */; }; @@ -101,13 +97,10 @@ 3C0474052B3F7E5F0012AE95 /* MCEndpointFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCEndpointFilter.h; sourceTree = ""; }; 3C04740B2B4604CF0012AE95 /* MCCryptoUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCryptoUtils.h; sourceTree = ""; }; 3C04740D2B4605B40012AE95 /* MCCryptoUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCCryptoUtils.mm; sourceTree = ""; }; - 3C0D9CDF2920A30C00D3332B /* CommissionableDataProviderImpl.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CommissionableDataProviderImpl.hpp; sourceTree = ""; }; 3C2346202B362B4F00FA276E /* MCCastingPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCastingPlayer.h; sourceTree = ""; }; 3C2346222B362B9500FA276E /* MCCastingPlayerDiscovery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCastingPlayerDiscovery.h; sourceTree = ""; }; 3C2346242B362BBB00FA276E /* MCCastingPlayerDiscovery.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCCastingPlayerDiscovery.mm; sourceTree = ""; }; 3C2696FA2B4A5FC50026E771 /* MCEndpointFilter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MCEndpointFilter.m; sourceTree = ""; }; - 3C26AC8B2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DeviceAttestationCredentialsProviderImpl.hpp; sourceTree = ""; }; - 3C26AC8F2927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DeviceAttestationCredentialsProviderImpl.mm; sourceTree = ""; }; 3C26AC91292700AD00BA6881 /* DeviceAttestationCredentialsHolder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeviceAttestationCredentialsHolder.h; sourceTree = ""; }; 3C26AC9229282B8100BA6881 /* DeviceAttestationCredentialsHolder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DeviceAttestationCredentialsHolder.m; sourceTree = ""; }; 3C4AE64E286A7D40005B52A4 /* OnboardingPayload.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OnboardingPayload.h; sourceTree = ""; }; @@ -131,7 +124,6 @@ 3C4F52292B51DFAE00BB8A10 /* MCCommand_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCommand_Internal.h; sourceTree = ""; }; 3C4F522B2B51E02800BB8A10 /* MCCommand.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCCommand.mm; sourceTree = ""; }; 3C621CA42B605A6A005CDBA3 /* MCAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAttribute.h; sourceTree = ""; }; - 3C621CA62B605AA1005CDBA3 /* MCObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCObserver.h; sourceTree = ""; }; 3C621CA82B605C52005CDBA3 /* MCAttribute_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCAttribute_Internal.h; sourceTree = ""; }; 3C621CAA2B605C6E005CDBA3 /* MCAttribute.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCAttribute.mm; sourceTree = ""; }; 3C66FBFA2903279A00B63FE7 /* AppParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppParameters.h; sourceTree = ""; }; @@ -146,6 +138,10 @@ 3C9437882B364F5E0096E5F4 /* MCCastingPlayer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCCastingPlayer.mm; sourceTree = ""; }; 3C9437912B3B478E0096E5F4 /* MCErrorUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCErrorUtils.h; sourceTree = ""; }; 3C9437932B3B47A10096E5F4 /* MCErrorUtils.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCErrorUtils.mm; sourceTree = ""; }; + 3C996C252BD31FD60027BD8A /* DataSourceCompat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataSourceCompat.h; sourceTree = ""; }; + 3C996C262BD31FEA0027BD8A /* DataSourceCompat.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DataSourceCompat.mm; sourceTree = ""; }; + 3C996C292BD6F4800027BD8A /* CastingPlayerDiscoveryListenerCompat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CastingPlayerDiscoveryListenerCompat.h; sourceTree = ""; }; + 3C996C2A2BD6F4950027BD8A /* CastingPlayerDiscoveryListenerCompat.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CastingPlayerDiscoveryListenerCompat.mm; sourceTree = ""; }; 3CA1CA7728E243750023ED44 /* MediaPlaybackTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaPlaybackTypes.h; sourceTree = ""; }; 3CCB871D2869085400771BAD /* MatterTvCastingBridge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MatterTvCastingBridge.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3CCB87202869085400771BAD /* MatterTvCastingBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MatterTvCastingBridge.h; sourceTree = ""; }; @@ -153,10 +149,7 @@ 3CCB8739286A593700771BAD /* DiscoveredNodeData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DiscoveredNodeData.mm; sourceTree = ""; }; 3CCB873A286A593700771BAD /* CastingServerBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CastingServerBridge.h; sourceTree = ""; }; 3CCB873B286A593700771BAD /* DiscoveredNodeData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscoveredNodeData.h; sourceTree = ""; }; - 3CCB873C286A593700771BAD /* ConversionUtils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ConversionUtils.hpp; sourceTree = ""; }; 3CCB873D286A593700771BAD /* CastingServerBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CastingServerBridge.mm; sourceTree = ""; }; - 3CCB873E286A593700771BAD /* ConversionUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ConversionUtils.mm; sourceTree = ""; }; - 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommissionerDiscoveryDelegateImpl.h; sourceTree = ""; }; 3CD73F162A9E6884009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCRotatingDeviceIdUniqueIdProvider.h; sourceTree = ""; }; 3CD73F182A9E68A7009D82D1 /* MCRotatingDeviceIdUniqueIdProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCRotatingDeviceIdUniqueIdProvider.mm; sourceTree = ""; }; 3CD73F1B2A9E8396009D82D1 /* MCCommissionableDataProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCommissionableDataProvider.h; sourceTree = ""; }; @@ -165,7 +158,6 @@ 3CD73F212A9EA077009D82D1 /* MCDeviceAttestationCredentials.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCDeviceAttestationCredentials.mm; sourceTree = ""; }; 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommissioningCallbackHandlers.h; sourceTree = ""; }; 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CommissioningCallbackHandlers.m; sourceTree = ""; }; - 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CommissionableDataProviderImpl.mm; sourceTree = ""; }; 3CF71C092A992D0D003A5CE5 /* MCCastingApp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCCastingApp.h; sourceTree = ""; }; 3CF71C0B2A992D25003A5CE5 /* MCCastingApp.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MCCastingApp.mm; sourceTree = ""; }; 3CF71C0D2A992DA2003A5CE5 /* MCDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MCDataSource.h; sourceTree = ""; }; @@ -201,29 +193,42 @@ 39DB29E82B9A3B1D0071334A /* MCCommandPayloads.h */, 39DB29EA2B9A3B2D0071334A /* MCCommandPayloads.mm */, 399049A62B9FC4ED000C91F0 /* MCCommandPayloads_Internal.h */, + 3C4F521F2B507C4A00BB8A10 /* MCEndpointClusterType.h */, ); path = "zap-generated"; sourceTree = ""; }; - 3C94378A2B3654720096E5F4 /* Core */ = { - isa = PBXGroup; - children = ( - ); - path = Core; - sourceTree = ""; - }; - 3C94378B2B36547A0096E5F4 /* Support */ = { - isa = PBXGroup; - children = ( - ); - path = Support; - sourceTree = ""; - }; - 3C94378C2B3654960096E5F4 /* Clusters */ = { + 3C996C282BD3287D0027BD8A /* compat-shim */ = { isa = PBXGroup; children = ( + 3CCB873A286A593700771BAD /* CastingServerBridge.h */, + 3CCB873D286A593700771BAD /* CastingServerBridge.mm */, + 3C996C252BD31FD60027BD8A /* DataSourceCompat.h */, + 3C996C262BD31FEA0027BD8A /* DataSourceCompat.mm */, + 3C996C292BD6F4800027BD8A /* CastingPlayerDiscoveryListenerCompat.h */, + 3C996C2A2BD6F4950027BD8A /* CastingPlayerDiscoveryListenerCompat.mm */, + 3C66FBFA2903279A00B63FE7 /* AppParameters.h */, + 3C66FBFB290327BB00B63FE7 /* AppParameters.mm */, + 3CCB873B286A593700771BAD /* DiscoveredNodeData.h */, + 3CCB8739286A593700771BAD /* DiscoveredNodeData.mm */, + 3C4AE64E286A7D40005B52A4 /* OnboardingPayload.h */, + 3C4AE64F286A7D4D005B52A4 /* OnboardingPayload.m */, + 3C81C74E28F7A7AE001CB9D1 /* ContentApp.h */, + 3C81C74B28F7A777001CB9D1 /* ContentApp.mm */, + 3C81C75128F7A7DF001CB9D1 /* VideoPlayer.h */, + 3C81C74F28F7A7D3001CB9D1 /* VideoPlayer.m */, + 3C4E53B428E5593700F293E8 /* ContentLauncherTypes.h */, + 3C4E53B528E5595A00F293E8 /* ContentLauncherTypes.mm */, + 3CA1CA7728E243750023ED44 /* MediaPlaybackTypes.h */, + 3C4E53AF28E4F28100F293E8 /* MediaPlaybackTypes.mm */, + 3C4E53B328E5185F00F293E8 /* TargetNavigatorTypes.h */, + 3C4E53B128E5184C00F293E8 /* TargetNavigatorTypes.mm */, + 3C26AC91292700AD00BA6881 /* DeviceAttestationCredentialsHolder.h */, + 3C26AC9229282B8100BA6881 /* DeviceAttestationCredentialsHolder.m */, + 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */, + 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */, ); - path = Clusters; + path = "compat-shim"; sourceTree = ""; }; 3CCB87132869085400771BAD = { @@ -246,10 +251,8 @@ 3CCB871F2869085400771BAD /* MatterTvCastingBridge */ = { isa = PBXGroup; children = ( + 3C996C282BD3287D0027BD8A /* compat-shim */, 395241F42B854EA700F7DB91 /* zap-generated */, - 3C94378A2B3654720096E5F4 /* Core */, - 3C94378B2B36547A0096E5F4 /* Support */, - 3C94378C2B3654960096E5F4 /* Clusters */, 3CCB87202869085400771BAD /* MatterTvCastingBridge.h */, 3CF71C092A992D0D003A5CE5 /* MCCastingApp.h */, 3CF71C0B2A992D25003A5CE5 /* MCCastingApp.mm */, @@ -267,11 +270,9 @@ 3C4F52272B51DB3000BB8A10 /* MCCommand.h */, 3C4F52292B51DFAE00BB8A10 /* MCCommand_Internal.h */, 3C4F522B2B51E02800BB8A10 /* MCCommand.mm */, - 3C621CA62B605AA1005CDBA3 /* MCObserver.h */, 3C621CA42B605A6A005CDBA3 /* MCAttribute.h */, 3C621CA82B605C52005CDBA3 /* MCAttribute_Internal.h */, 3C621CAA2B605C6E005CDBA3 /* MCAttribute.mm */, - 3C4F521F2B507C4A00BB8A10 /* MCEndpointClusterType.h */, 3C4F52132B4F31DC00BB8A10 /* MCDeviceTypeStruct.h */, 3C4F52152B4F31FA00BB8A10 /* MCDeviceTypeStruct.m */, 3C0474052B3F7E5F0012AE95 /* MCEndpointFilter.h */, @@ -296,35 +297,6 @@ 3C04740D2B4605B40012AE95 /* MCCryptoUtils.mm */, 39BF57CA2B8E54F80081653C /* NSDataSpanConversion.h */, 39BF57C82B8D66540081653C /* NSStringSpanConversion.h */, - 3CCB873A286A593700771BAD /* CastingServerBridge.h */, - 3CCB873D286A593700771BAD /* CastingServerBridge.mm */, - 3C66FBFA2903279A00B63FE7 /* AppParameters.h */, - 3C66FBFB290327BB00B63FE7 /* AppParameters.mm */, - 3CCB873B286A593700771BAD /* DiscoveredNodeData.h */, - 3CCB8739286A593700771BAD /* DiscoveredNodeData.mm */, - 3CCB873C286A593700771BAD /* ConversionUtils.hpp */, - 3CCB873E286A593700771BAD /* ConversionUtils.mm */, - 3C4AE64E286A7D40005B52A4 /* OnboardingPayload.h */, - 3C4AE64F286A7D4D005B52A4 /* OnboardingPayload.m */, - 3C81C74E28F7A7AE001CB9D1 /* ContentApp.h */, - 3C81C74B28F7A777001CB9D1 /* ContentApp.mm */, - 3C81C75128F7A7DF001CB9D1 /* VideoPlayer.h */, - 3C81C74F28F7A7D3001CB9D1 /* VideoPlayer.m */, - 3C4E53B428E5593700F293E8 /* ContentLauncherTypes.h */, - 3C4E53B528E5595A00F293E8 /* ContentLauncherTypes.mm */, - 3CA1CA7728E243750023ED44 /* MediaPlaybackTypes.h */, - 3C4E53AF28E4F28100F293E8 /* MediaPlaybackTypes.mm */, - 3C4E53B328E5185F00F293E8 /* TargetNavigatorTypes.h */, - 3C4E53B128E5184C00F293E8 /* TargetNavigatorTypes.mm */, - 3C26AC91292700AD00BA6881 /* DeviceAttestationCredentialsHolder.h */, - 3C26AC9229282B8100BA6881 /* DeviceAttestationCredentialsHolder.m */, - 3C26AC8B2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp */, - 3C26AC8F2927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm */, - 3C0D9CDF2920A30C00D3332B /* CommissionableDataProviderImpl.hpp */, - 3CE868F32946D76200FCB92B /* CommissionableDataProviderImpl.mm */, - 3CD6D019298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h */, - 3CE5ECCD2A673B30007CF331 /* CommissioningCallbackHandlers.h */, - 3CE5ECCF2A673E2C007CF331 /* CommissioningCallbackHandlers.m */, ); path = MatterTvCastingBridge; sourceTree = ""; @@ -339,12 +311,10 @@ 3C69204C2AA136BA00D0F613 /* MCCommonCaseDeviceServerInitParamsProvider.h in Headers */, 3C2346212B362B4F00FA276E /* MCCastingPlayer.h in Headers */, 3C2346232B362B9500FA276E /* MCCastingPlayerDiscovery.h in Headers */, - 3CD6D01A298CDA2100D7569A /* CommissionerDiscoveryDelegateImpl.h in Headers */, 3CF71C0E2A992DA2003A5CE5 /* MCDataSource.h in Headers */, 3C4F52142B4F31DC00BB8A10 /* MCDeviceTypeStruct.h in Headers */, 39BF57CD2B8FC0EF0081653C /* MCClusterObjects.h in Headers */, 39D4D2502B97942D00BF3CFE /* MCCommandObjects.h in Headers */, - 3C26AC8C2926FE0C00BA6881 /* DeviceAttestationCredentialsProviderImpl.hpp in Headers */, 3C621CA52B605A6A005CDBA3 /* MCAttribute.h in Headers */, 3CD73F1C2A9E8396009D82D1 /* MCCommissionableDataProvider.h in Headers */, 3C4F521E2B4F4B3B00BB8A10 /* MCEndpoint_Internal.h in Headers */, @@ -364,8 +334,6 @@ 3CCB8740286A593700771BAD /* CastingServerBridge.h in Headers */, 3CE5ECCE2A673B30007CF331 /* CommissioningCallbackHandlers.h in Headers */, 39589F162B91556B00BE040C /* MCInteractionModelStructs.h in Headers */, - 3CCB8742286A593700771BAD /* ConversionUtils.hpp in Headers */, - 3C621CA72B605AA1005CDBA3 /* MCObserver.h in Headers */, 3C9437922B3B478E0096E5F4 /* MCErrorUtils.h in Headers */, 3C4F52222B507C9300BB8A10 /* MCCluster.h in Headers */, 3CCB8741286A593700771BAD /* DiscoveredNodeData.h in Headers */, @@ -486,8 +454,8 @@ 3C4F522C2B51E02800BB8A10 /* MCCommand.mm in Sources */, 3C4E53B628E5595A00F293E8 /* ContentLauncherTypes.mm in Sources */, 3C81C75028F7A7D3001CB9D1 /* VideoPlayer.m in Sources */, - 3CCB8744286A593700771BAD /* ConversionUtils.mm in Sources */, 3CF71C0C2A992D25003A5CE5 /* MCCastingApp.mm in Sources */, + 3CC3979E2BE9857C00465462 /* MCCastingPlayer.mm in Sources */, 3C621CAB2B605C6E005CDBA3 /* MCAttribute.mm in Sources */, 3C4F52122B4E18ED00BB8A10 /* MCEndpoint.mm in Sources */, 3C4E53B028E4F28100F293E8 /* MediaPlaybackTypes.mm in Sources */, @@ -499,14 +467,14 @@ 3C4F52242B507CA800BB8A10 /* MCCluster.mm in Sources */, 3C66FBFC290327BB00B63FE7 /* AppParameters.mm in Sources */, 3C9437942B3B47A10096E5F4 /* MCErrorUtils.mm in Sources */, - 3CE868F42946D76200FCB92B /* CommissionableDataProviderImpl.mm in Sources */, 3C26AC9329282B8100BA6881 /* DeviceAttestationCredentialsHolder.m in Sources */, - 3C26AC902927008900BA6881 /* DeviceAttestationCredentialsProviderImpl.mm in Sources */, + 3C996C272BD31FEA0027BD8A /* DataSourceCompat.mm in Sources */, 3CCB873F286A593700771BAD /* DiscoveredNodeData.mm in Sources */, 39D4D2522B97943D00BF3CFE /* MCCommandObjects.mm in Sources */, 3C4F52162B4F31FA00BB8A10 /* MCDeviceTypeStruct.m in Sources */, 3C2696FB2B4A5FC50026E771 /* MCEndpointFilter.m in Sources */, 3C81C74C28F7A777001CB9D1 /* ContentApp.mm in Sources */, + 3C996C2B2BD6F4960027BD8A /* CastingPlayerDiscoveryListenerCompat.mm in Sources */, 3CF71C122A993298003A5CE5 /* MCCommissionableData.mm in Sources */, 3C4AE650286A7D4D005B52A4 /* OnboardingPayload.m in Sources */, ); diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h deleted file mode 100644 index 2489f982fb0645..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.h +++ /dev/null @@ -1,1263 +0,0 @@ -/** - * - * Copyright (c) 2020-2023 Project CHIP Authors - * - * 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. - */ - -#import "AppParameters.h" -#import "CommissioningCallbackHandlers.h" -#import "ContentApp.h" -#import "ContentLauncherTypes.h" -#import "DiscoveredNodeData.h" -#import "MatterError.h" -#import "MediaPlaybackTypes.h" -#import "OnboardingPayload.h" -#import "TargetNavigatorTypes.h" -#import "VideoPlayer.h" -#import - -#ifndef CastingServerBridge_h -#define CastingServerBridge_h - -@interface CastingServerBridge : NSObject - -+ (CastingServerBridge * _Nullable)getSharedInstance; - -- (MatterError * _Nonnull)initializeApp:(AppParameters * _Nullable)appParameters - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - initAppStatusHandler:(nullable void (^)(bool))initAppStatusHandler; - -- (void)setDacHolder:(DeviceAttestationCredentialsHolder * _Nonnull)deviceAttestationCredentials - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - setDacHolderStatus:(void (^_Nonnull)(MatterError * _Nonnull))setDacHolderStatus; - -/*! - @brief Browse for on-network commissioner TVs - - @param clientQueue Queue to dispatch the call to the discoveryRequestSentHandler on - - @param discoveryRequestSentHandler Handler to call after the Commissioner discovery request has been sent - */ -- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue - discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler - discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler; - -/*! - @brief Retrieve a discovered commissioner TV - - @param index Index in the list of discovered commissioners - - @param clientQueue Queue to dispatch the call to the discoveredCommissionerHandler on - - @param discoveredCommissionerHandler Handler called synchronously after a discovered commissioner has been retrieved - */ -- (void)getDiscoveredCommissioner:(int)index - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler; - -/*! - @brief Send a User Directed Commissioning request to a commissioner TV - - @param commissionerIpAddress IP address of the commissioner - - @param commissionerPort Port number at which the commissioner is listening for User Directed Commissioning requests - - @param platformInterface Platform representation of the commissioner's IP address's interface - - @param clientQueue Queue to dispatch the call to the udcRequestSentHandler on - - @param udcRequestSentHandler Handler to call on sending the User Directed Commissioning request - */ -- (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIpAddress - commissionerPort:(uint16_t)commissionerPort - platformInterface:(unsigned int)platformInterface - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler; - -/*! - @brief Send a User Directed Commissioning request to a commissioner TV - - @param commissioner Commissioner to request commissioning from - - @param clientQueue Queue to dispatch the call to the udcRequestSentHandler on - - @param udcRequestSentHandler Handler to call on sending the User Directed Commissioning request - */ -- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler; - -/*! - @brief Return the onboarding payload for this app (setup passcode, discriminator) - - @return Onboarding payload - */ -- (OnboardingPayload * _Nonnull)getOnboardingPayload; - -/*! - @brief Request opening of a basic commissioning window - - @param clientQueue Queue to dispatch the call to the commissioningWindowRequestedHandler on - - @param commissioningCallbackHandlers Optional parameter to specific handlers for callbacks during commissioning - - @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established - - @param onConnectionFailureCallback Handles MatterError if there is a failure in establishing connection - - @param onNewOrUpdatedEndpointCallback Handles a ContentApp * for each new ContentApp is found. May be called multiple times based - on the number of ContentApp - */ -- (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue - commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; - -/*! - @brief Gets the list of VideoPlayers currently connected - - @param clientQueue Queue to invoke callbacks on - - @param activeTargetVideoPlayersHandler Handles NSMutableArray of active/currently connected VideoPlayers. Nil, if no such - VideoPlayers are found. - */ -- (void)getActiveTargetVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue - activeTargetVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))activeTargetVideoPlayersHandler; - -/*! - @brief Reads all previously connected video players from cache. These are not connected. - - @param clientQueue Queue to invoke callbacks on - - @param readCachedVideoPlayersHandler Handles NSMutableArray of VideoPlayers from the cache. Empty, if no such VideoPlayers are - found. - */ -- (void)readCachedVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue - readCachedVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))readCachedVideoPlayersHandler; - -/*! - @brief Verify if a connection exists or connect to the VideoPlayer passed in as parameter. - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handles MatterError and called after the request has been sent - - @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established - - @param onConnectionFailureCallback Handles MatterError if there is a failure in establishing connection - - @param onNewOrUpdatedEndpointCallback Handles a ContentApp * for each new ContentApp is found. May be called multiple times based - on the number of ContentApp - */ -- (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(nullable void (^)(MatterError * _Nonnull))requestSentHandler - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; - -/*! - @brief Tears down all active subscriptions. - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Called after the request has been sent - */ -- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler; - -/*! - @brief Mark any open session with the currently connected Video player as expired. - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Called after the request has been sent - */ -- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler; - -/*! - @brief Purge data cached by the Matter casting library - - @param clientQueue Queue to invoke callbacks on - - @param responseHandler Called when purgeCache completes - */ -- (void)purgeCache:(dispatch_queue_t _Nonnull)clientQueue responseHandler:(void (^_Nonnull)(MatterError * _Nonnull))responseHandler; - -/*! - @brief Start the Matter server and reconnect to a previously connected Video Player (if any). This API is async - - @param clientQueue Queue to invoke callbacks on - - @param startMatterServerCompletionCallback Called after the Matter server has started and connected (or failed to connect) to a - previously connected video player (if any) are complete - */ -- (void)startMatterServer:(dispatch_queue_t _Nonnull)clientQueue - startMatterServerCompletionCallback:(nullable void (^)(MatterError * _Nonnull))startMatterServerCompletionCallback; - -/** - @brief Stop the Matter server - */ -- (void)stopMatterServer; - -/*! - @brief Send a ContentLauncher:LaunchURL request to a TV - - @param contentApp Content app endpoint to target - - @param contentUrl URL of the content to launch on the TV - - @param contentDisplayStr Display string value corresponding to the content - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)contentLauncher_launchUrl:(ContentApp * _Nonnull)contentApp - contentUrl:(NSString * _Nonnull)contentUrl - contentDisplayStr:(NSString * _Nonnull)contentDisplayStr - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a ContentLauncher:LaunchContent request to a TV - - @param contentApp Content app endpoint to target - - @param contentSearch Indicates the content to launch - - @param autoPlay Play Best match automatically if true, otherwise display matches - - @param data App specific data to be passed to the TV - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)contentLauncher_launchContent:(ContentApp * _Nonnull)contentApp - contentSearch:(ContentLauncher_ContentSearch * _Nonnull)contentSearch - autoPlay:(bool)autoPlay - data:(NSString * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Subscribe to ContentLauncher:SupportedStreamingProtocols - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)contentLauncher_subscribeSupportedStreamingProtocols:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint32_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Send a LevelControl:Step request to a TV - - @param contentApp Content app endpoint to target - - @param stepMode Increase (0x00) or Decrease (0x01) the device’s level - - @param stepSize Number of units to step the device's level by - - @param transitionTime Time that SHALL be taken to perform the step, in tenths of a second - - @param optionMask Used to create a temporary Options bitmap to construct the Options attribute - - @param optionOverride Used to create a temporary Options bitmap to construct the Options attribute - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)levelControl_step:(ContentApp * _Nonnull)contentApp - stepMode:(uint8_t)stepMode - stepSize:(uint8_t)stepSize - transitionTime:(uint16_t)transitionTime - optionMask:(uint8_t)optionMask - optionOverride:(uint8_t)optionOverride - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a LevelControl:MoveToLevel request to a TV - - @param contentApp Content app endpoint to target - - @param level the level to which the device should move - - @param transitionTime Time that SHALL be taken to perform the step, in tenths of a second - - @param optionMask Used to create a temporary Options bitmap to construct the Options attribute - - @param optionOverride Used to create a temporary Options bitmap to construct the Options attribute - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)levelControl_moveToLevel:(ContentApp * _Nonnull)contentApp - level:(uint8_t)level - transitionTime:(uint16_t)transitionTime - optionMask:(uint8_t)optionMask - optionOverride:(uint8_t)optionOverride - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Subscribe to LevelControl:CurrentLevel - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)levelControl_subscribeCurrentLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to LevelControl:MinLevel - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)levelControl_subscribeMinLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to LevelControl:MaxLevel - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)levelControl_subscribeMaxLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Send a MediaPlayback:Play request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_play:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:Pause request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_pause:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:StopPlayback request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_stopPlayback:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:Next request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_next:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:Previous request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_previous:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:FastForward request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_fastForward:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:Rewind request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_rewind:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:StartOver request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_startOver:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:Seek request to a TV - - @param contentApp Content app endpoint to target - - @param position the position (in milliseconds) in the media to seek to - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_seek:(ContentApp * _Nonnull)contentApp - position:(uint64_t)position - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:SkipForward request to a TV - - @param contentApp Content app endpoint to target - - @param deltaPositionMilliseconds the duration of the time span to skip forward in the media, in milliseconds - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_skipForward:(ContentApp * _Nonnull)contentApp - deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a MediaPlayback:SkipBackward request to a TV - - @param contentApp Content app endpoint to target - - @param deltaPositionMilliseconds the duration of the time span to skip backward in the media, in milliseconds - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)mediaPlayback_skipBackward:(ContentApp * _Nonnull)contentApp - deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Subscribe to MediaPlayback:CurrentState - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeCurrentState:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackState))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:StartTime - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeStartTime:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:Duration - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeDuration:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:SampledPosition - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeSampledPosition:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackPosition * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:PlaybackSpeed - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribePlaybackSpeed:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(float))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:SeekRangeEnd - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeSeekRangeEnd:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to MediaPlayback:SeekRangeStart - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)mediaPlayback_subscribeSeekRangeStart:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; -/*! - @brief Send a ApplicationLauncher:LaunchApp request to a TV - - @param contentApp Content app endpoint to target - - @param catalogVendorId CSA-issued vendor ID for the catalog - - @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" - - @param data optional app-specific data to be sent to the app - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)applicationLauncher_launchApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - data:(NSData * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a ApplicationLauncher:StopApp request to a TV - - @param contentApp Content app endpoint to target - - @param catalogVendorId CSA-issued vendor ID for the catalog - - @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)applicationLauncher_stopApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a ApplicationLauncher:HideApp request to a TV - - @param contentApp Content app endpoint to target - - @param catalogVendorId CSA-issued vendor ID for the catalog - - @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)applicationLauncher_hideApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a TargetNavigator:NavigateTarget request to a TV - - @param contentApp Content app endpoint to target - - @param target Identifier for the target for UX navigation, contained within one of the TargetInfo objects in the TargetList - attribute list. - - @param data Optional app-specific data - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)targetNavigator_navigateTarget:(ContentApp * _Nonnull)contentApp - target:(uint8_t)target - data:(NSString * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Subscribe to TargetNavigator:TargetList - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)targetNavigator_subscribeTargetList:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSMutableArray * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to TargetNavigator:CurrentTarget - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)targetNavigator_subscribeCurrentTarget:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Send a KeypadInput:SendKey request to a TV - - @param contentApp Content app endpoint to target - - @param keyCode Key Code to process. If a second SendKey request with the same KeyCode value is received within 200ms, then the - endpoint will consider the first key press to be a press and hold. When such a repeat KeyCode value is not received within 200ms, - then the endpoint will consider the last key press to be a release. - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)keypadInput_sendKey:(ContentApp * _Nonnull)contentApp - keyCode:(uint8_t)keyCode - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Subscribe to ApplicationBasic:VendorName - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)applicationBasic_subscribeVendorName:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to ApplicationBasic:VendorID - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)applicationBasic_subscribeVendorID:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to ApplicationBasic:ApplicationName - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)applicationBasic_subscribeApplicationName:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to ApplicationBasic:ProductID - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)applicationBasic_subscribeProductID:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint16_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Subscribe to ApplicationBasic:ApplicationVersion - - @param contentApp Content app endpoint to target - - @param minInterval Minimum interval between attribute read reports - - @param maxInterval Maximum interval between attribute read reports - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - - @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully - */ -- (void)applicationBasic_subscribeApplicationVersion:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; - -/*! - @brief Read ApplicationBasic:VendorName - - @param contentApp Content app endpoint to target - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - */ -- (void)applicationBasic_readVendorName:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; - -/*! - @brief Read ApplicationBasic:VendorID - - @param contentApp Content app endpoint to target - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - */ -- (void)applicationBasic_readVendorID:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; - -/*! - @brief Read ApplicationBasic:ApplicationName - - @param contentApp Content app endpoint to target - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - */ -- (void)applicationBasic_readApplicationName:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; - -/*! - @brief Read ApplicationBasic:ProductID - - @param contentApp Content app endpoint to target - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - */ -- (void)applicationBasic_readProductID:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint16_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; - -/*! - @brief Read ApplicationBasic:ApplicationVersion - - @param contentApp Content app endpoint to target - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - - @param successCallback Callback for when a read report is successfully received - - @param failureCallback Callback for when there is a failure in receiving a read report - */ -- (void)applicationBasic_readApplicationVersion:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; -/*! - @brief Send a OnOff:On request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)onOff_on:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a OnOff:Off request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)onOff_off:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; - -/*! - @brief Send a OnOff:Toggle request to a TV - - @param contentApp Content app endpoint to target - - @param responseCallback Callback for when the response has been received - - @param clientQueue Queue to invoke callbacks on - - @param requestSentHandler Handler to call on sending the request - */ -- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler; -@end -#endif /* CastingServerBridge_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.hpp b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.hpp deleted file mode 100644 index 979c7c72f5e057..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Copyright (c) 2022 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 -#include -#include -#include -#include - -class CommissionableDataProviderImpl : public chip::DeviceLayer::CommissionableDataProvider -{ -public: - CHIP_ERROR Initialize(chip::ByteSpan * spake2pVerifierBase64, chip::ByteSpan * spake2pSaltBase64, - uint32_t spake2pIterationCount, uint32_t setupPasscode, uint16_t discriminator); - CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; - CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override - { - // We don't support overriding the discriminator post-init (it is deprecated!) - return CHIP_ERROR_NOT_IMPLEMENTED; - } - CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override; - CHIP_ERROR GetSpake2pSalt(chip::MutableByteSpan & saltBuf) override; - CHIP_ERROR GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen) override; - CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override; - CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override - { - // We don't support overriding the passcode post-init (it is deprecated!) - return CHIP_ERROR_NOT_IMPLEMENTED; - } - -private: - friend CommissionableDataProviderImpl & CommissionableDataProviderMgrImpl(); - static CommissionableDataProviderImpl sInstance; - bool mFirstUpdated = false; - std::vector mSerializedPaseVerifier; - std::vector mPaseSalt; - uint32_t mPaseIterationCount = 0; - chip::Optional mSetupPasscode; - uint16_t mDiscriminator = 0; -}; - -inline CommissionableDataProviderImpl & CommissionableDataProviderMgrImpl() -{ - return CommissionableDataProviderImpl::sInstance; -} diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.mm deleted file mode 100644 index 40c2efcd99cb65..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionableDataProviderImpl.mm +++ /dev/null @@ -1,209 +0,0 @@ -/* - * - * Copyright (c) 2022 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 "CommissionableDataProviderImpl.hpp" - -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace chip; -using namespace chip::Crypto; - -namespace { - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT 1000 -#endif - -CHIP_ERROR GeneratePaseSalt(std::vector & spake2pSaltVector) -{ - constexpr size_t kSaltLen = kSpake2p_Max_PBKDF_Salt_Length; - spake2pSaltVector.resize(kSaltLen); - return DRBG_get_bytes(spake2pSaltVector.data(), spake2pSaltVector.size()); -} - -} // namespace - -CommissionableDataProviderImpl CommissionableDataProviderImpl::sInstance; - -CHIP_ERROR CommissionableDataProviderImpl::Initialize(chip::ByteSpan * spake2pVerifierBase64, chip::ByteSpan * spake2pSaltBase64, - uint32_t spake2pIterationCount, uint32_t setupPasscode, uint16_t discriminator) -{ - VerifyOrReturnLogError(discriminator <= chip::kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT); - - if (spake2pIterationCount == 0) { - spake2pIterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT; - } - VerifyOrReturnLogError( - static_cast(spake2pIterationCount) >= kSpake2p_Min_PBKDF_Iterations, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnLogError( - static_cast(spake2pIterationCount) <= kSpake2p_Max_PBKDF_Iterations, CHIP_ERROR_INVALID_ARGUMENT); - - const bool havePaseVerifier = (spake2pVerifierBase64 != nullptr); - const bool havePaseSalt = (spake2pSaltBase64 != nullptr); - VerifyOrReturnLogError(!havePaseVerifier || (havePaseVerifier && havePaseSalt), CHIP_ERROR_INVALID_ARGUMENT); - - CHIP_ERROR err; - // read verifier from paramter if provided - Spake2pVerifier providedVerifier; - std::vector serializedSpake2pVerifier(kSpake2p_VerifierSerialized_Length); - if (havePaseVerifier) { - size_t maxBase64Size = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length); - VerifyOrReturnLogError(static_cast(spake2pVerifierBase64->size()) <= maxBase64Size, CHIP_ERROR_INVALID_ARGUMENT); - - size_t decodedLen = chip::Base64Decode32(reinterpret_cast(spake2pVerifierBase64->data()), - static_cast(spake2pVerifierBase64->size()), reinterpret_cast(serializedSpake2pVerifier.data())); - VerifyOrReturnLogError(decodedLen == chip::Crypto::kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT); - - chip::MutableByteSpan verifierSpan { serializedSpake2pVerifier.data(), decodedLen }; - err = providedVerifier.Deserialize(verifierSpan); - VerifyOrReturnLogError(err == CHIP_NO_ERROR, err); - - ChipLogProgress(Support, "Got externally provided verifier, using it."); - } - - // read salt from paramter if provided or generate one - std::vector spake2pSalt(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length); - if (!havePaseSalt) { - ChipLogProgress(Support, "CommissionableDataProviderImpl didn't get a PASE salt, generating one."); - err = GeneratePaseSalt(spake2pSalt); - VerifyOrReturnLogError(err == CHIP_NO_ERROR, err); - } else { - size_t maxBase64Size = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length); - VerifyOrReturnLogError(static_cast(spake2pSaltBase64->size()) <= maxBase64Size, CHIP_ERROR_INVALID_ARGUMENT); - - size_t decodedLen = chip::Base64Decode32(reinterpret_cast(spake2pSaltBase64->data()), - static_cast(spake2pSaltBase64->size()), reinterpret_cast(spake2pSalt.data())); - VerifyOrReturnLogError(decodedLen >= chip::Crypto::kSpake2p_Min_PBKDF_Salt_Length - && decodedLen <= chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length, - CHIP_ERROR_INVALID_ARGUMENT); - spake2pSalt.resize(decodedLen); - } - - // generate verifier from passcode if provided - const bool havePasscode = (setupPasscode > kMinSetupPasscode && setupPasscode < kMaxSetupPasscode); - Spake2pVerifier passcodeVerifier; - std::vector serializedPasscodeVerifier(kSpake2p_VerifierSerialized_Length); - chip::MutableByteSpan saltSpan { spake2pSalt.data(), spake2pSalt.size() }; - if (havePasscode) { - uint32_t u32SetupPasscode = static_cast(setupPasscode); - err = passcodeVerifier.Generate(spake2pIterationCount, saltSpan, u32SetupPasscode); - VerifyOrReturnLogError(err == CHIP_NO_ERROR, err); - - chip::MutableByteSpan verifierSpan { serializedPasscodeVerifier.data(), serializedPasscodeVerifier.size() }; - err = passcodeVerifier.Serialize(verifierSpan); - VerifyOrReturnLogError(err == CHIP_NO_ERROR, err); - } - - // Make sure we actually have a verifier - VerifyOrReturnLogError(havePasscode || havePaseVerifier, CHIP_ERROR_INVALID_ARGUMENT); - - // If both passcode and external verifier were provided, validate they match, otherwise - // it's ambiguous. - if (havePasscode && havePaseVerifier) { - VerifyOrReturnLogError(serializedPasscodeVerifier == serializedSpake2pVerifier, CHIP_ERROR_INVALID_ARGUMENT); - ChipLogProgress(Support, "Validated externally provided passcode matches the one generated from provided passcode."); - } - - // External PASE verifier takes precedence when present (even though it is identical to passcode-based - // one when the latter is present). - if (havePaseVerifier) { - mSerializedPaseVerifier = std::move(serializedSpake2pVerifier); - } else { - mSerializedPaseVerifier = std::move(serializedPasscodeVerifier); - } - mDiscriminator = discriminator; - mPaseSalt = std::move(spake2pSalt); - mPaseIterationCount = spake2pIterationCount; - if (havePasscode) { - mSetupPasscode.SetValue(setupPasscode); - } - - // Set to global CommissionableDataProvider once success first time - if (!mFirstUpdated) { - DeviceLayer::SetCommissionableDataProvider(this); - } - mFirstUpdated = true; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CommissionableDataProviderImpl::GetSetupDiscriminator(uint16_t & setupDiscriminator) -{ - VerifyOrReturnError(mFirstUpdated, CHIP_ERROR_INCORRECT_STATE); - setupDiscriminator = mDiscriminator; - return CHIP_NO_ERROR; -} - -CHIP_ERROR CommissionableDataProviderImpl::GetSpake2pIterationCount(uint32_t & iterationCount) -{ - ChipLogProgress(AppServer, "CommissionableDataProviderImpl::GetSpake2pIterationCount called"); - VerifyOrReturnLogError(mFirstUpdated, CHIP_ERROR_INCORRECT_STATE); - iterationCount = mPaseIterationCount; - return CHIP_NO_ERROR; -} - -CHIP_ERROR CommissionableDataProviderImpl::GetSpake2pSalt(chip::MutableByteSpan & saltBuf) -{ - ChipLogProgress(AppServer, "CommissionableDataProviderImpl::GetSpake2pSalt called"); - VerifyOrReturnError(mFirstUpdated, CHIP_ERROR_INCORRECT_STATE); - - VerifyOrReturnError(saltBuf.size() >= kSpake2p_Max_PBKDF_Salt_Length, CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(saltBuf.data(), mPaseSalt.data(), mPaseSalt.size()); - saltBuf.reduce_size(mPaseSalt.size()); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CommissionableDataProviderImpl::GetSpake2pVerifier(chip::MutableByteSpan & verifierBuf, size_t & outVerifierLen) -{ - ChipLogProgress(AppServer, "CommissionableDataProviderImpl::GetSpake2pVerifier called"); - VerifyOrReturnError(mFirstUpdated, CHIP_ERROR_INCORRECT_STATE); - - // By now, serialized verifier from Init should be correct size - VerifyOrReturnError(mSerializedPaseVerifier.size() == kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INTERNAL); - - outVerifierLen = mSerializedPaseVerifier.size(); - VerifyOrReturnError(verifierBuf.size() >= outVerifierLen, CHIP_ERROR_BUFFER_TOO_SMALL); - memcpy(verifierBuf.data(), mSerializedPaseVerifier.data(), mSerializedPaseVerifier.size()); - verifierBuf.reduce_size(mSerializedPaseVerifier.size()); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR CommissionableDataProviderImpl::GetSetupPasscode(uint32_t & setupPasscode) -{ - ChipLogProgress(AppServer, "CommissionableDataProviderImpl::GetSetupPasscode called"); - VerifyOrReturnError(mFirstUpdated, CHIP_ERROR_INCORRECT_STATE); - - // Pretend not implemented if we don't have a passcode value externally set - if (!mSetupPasscode.HasValue()) { - return CHIP_ERROR_NOT_IMPLEMENTED; - } - - setupPasscode = mSetupPasscode.Value(); - ChipLogProgress(AppServer, "CommissionableDataProviderImpl::GetSetupPasscode returning value %d", setupPasscode); - return CHIP_NO_ERROR; -} diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.hpp b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.hpp deleted file mode 100644 index 21d63ba88d2d05..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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 -#include -#include - -#include - -class DeviceAttestationCredentialsProviderImpl : public chip::Credentials::DeviceAttestationCredentialsProvider -{ -public: - DeviceAttestationCredentialsProviderImpl(chip::MutableByteSpan * certificationDeclaration, - chip::MutableByteSpan * firmwareInformation, - chip::MutableByteSpan * deviceAttestationCert, - chip::MutableByteSpan * productAttestationIntermediateCert, - SecKeyRef deviceAttestationCertPrivateKeyRef); - - CHIP_ERROR GetCertificationDeclaration(chip::MutableByteSpan & outCertificationDeclaration) override; - CHIP_ERROR GetFirmwareInformation(chip::MutableByteSpan & outFirmwareInformation) override; - CHIP_ERROR GetDeviceAttestationCert(chip::MutableByteSpan & outDeviceAttestationCert) override; - CHIP_ERROR GetProductAttestationIntermediateCert(chip::MutableByteSpan & outProductAttestationIntermediateCert) override; - CHIP_ERROR SignWithDeviceAttestationKey(const chip::ByteSpan & messageToSign, - chip::MutableByteSpan & outSignatureBuffer) override; - -private: - chip::MutableByteSpan mCertificationDeclaration; - chip::MutableByteSpan mFirmwareInformation; - chip::MutableByteSpan mDeviceAttestationCert; - chip::MutableByteSpan mProductAttestationIntermediateCert; - SecKeyRef mDeviceAttestationCertPrivateKeyRef; -}; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.mm deleted file mode 100644 index 7008ffba969e72..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsProviderImpl.mm +++ /dev/null @@ -1,164 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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 "DeviceAttestationCredentialsProviderImpl.hpp" - -#import -#import - -DeviceAttestationCredentialsProviderImpl::DeviceAttestationCredentialsProviderImpl(chip::MutableByteSpan * certificationDeclaration, - chip::MutableByteSpan * firmwareInformation, chip::MutableByteSpan * deviceAttestationCert, - chip::MutableByteSpan * productAttestationIntermediateCert, SecKeyRef deviceAttestationCertPrivateKeyRef) -{ - if (certificationDeclaration != nullptr) { - mCertificationDeclaration - = chip::MutableByteSpan(new uint8_t[certificationDeclaration->size()], certificationDeclaration->size()); - memcpy(mCertificationDeclaration.data(), certificationDeclaration->data(), certificationDeclaration->size()); - } - - if (firmwareInformation != nullptr) { - mFirmwareInformation = chip::MutableByteSpan(new uint8_t[firmwareInformation->size()], firmwareInformation->size()); - memcpy(mFirmwareInformation.data(), firmwareInformation->data(), firmwareInformation->size()); - } - - if (deviceAttestationCert != nullptr) { - mDeviceAttestationCert = chip::MutableByteSpan(new uint8_t[deviceAttestationCert->size()], deviceAttestationCert->size()); - memcpy(mDeviceAttestationCert.data(), deviceAttestationCert->data(), deviceAttestationCert->size()); - } - - if (productAttestationIntermediateCert != nullptr) { - mProductAttestationIntermediateCert = chip::MutableByteSpan( - new uint8_t[productAttestationIntermediateCert->size()], productAttestationIntermediateCert->size()); - memcpy(mProductAttestationIntermediateCert.data(), productAttestationIntermediateCert->data(), - productAttestationIntermediateCert->size()); - } - - mDeviceAttestationCertPrivateKeyRef = deviceAttestationCertPrivateKeyRef; -} - -CHIP_ERROR DeviceAttestationCredentialsProviderImpl::GetCertificationDeclaration( - chip::MutableByteSpan & outCertificationDeclaration) -{ - if (mCertificationDeclaration.size() > 0) { - if (outCertificationDeclaration.size() >= mCertificationDeclaration.size()) { - memcpy(outCertificationDeclaration.data(), mCertificationDeclaration.data(), mCertificationDeclaration.size()); - outCertificationDeclaration.reduce_size(mCertificationDeclaration.size()); - } else { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceAttestationCredentialsProviderImpl::GetFirmwareInformation(chip::MutableByteSpan & outFirmwareInformation) -{ - if (mFirmwareInformation.size() > 0) { - if (outFirmwareInformation.size() >= mFirmwareInformation.size()) { - memcpy(outFirmwareInformation.data(), mFirmwareInformation.data(), mFirmwareInformation.size()); - outFirmwareInformation.reduce_size(mFirmwareInformation.size()); - } else { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceAttestationCredentialsProviderImpl::GetDeviceAttestationCert(chip::MutableByteSpan & outDeviceAttestationCert) -{ - if (mDeviceAttestationCert.size() > 0) { - if (outDeviceAttestationCert.size() >= mDeviceAttestationCert.size()) { - memcpy(outDeviceAttestationCert.data(), mDeviceAttestationCert.data(), mDeviceAttestationCert.size()); - outDeviceAttestationCert.reduce_size(mDeviceAttestationCert.size()); - } else { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceAttestationCredentialsProviderImpl::GetProductAttestationIntermediateCert( - chip::MutableByteSpan & outProductAttestationIntermediateCert) -{ - if (mProductAttestationIntermediateCert.size() > 0) { - if (outProductAttestationIntermediateCert.size() >= mProductAttestationIntermediateCert.size()) { - memcpy(outProductAttestationIntermediateCert.data(), mProductAttestationIntermediateCert.data(), - mProductAttestationIntermediateCert.size()); - outProductAttestationIntermediateCert.reduce_size(mProductAttestationIntermediateCert.size()); - } else { - return CHIP_ERROR_BUFFER_TOO_SMALL; - } - } - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceAttestationCredentialsProviderImpl::SignWithDeviceAttestationKey( - const chip::ByteSpan & messageToSign, chip::MutableByteSpan & outSignatureBuffer) -{ - ChipLogProgress(AppServer, "DeviceAttestationCredentialsProviderImpl::SignWithDeviceAttestationKey called"); - - CHIP_ERROR result = CHIP_NO_ERROR; - CFDataRef dataToSign = nil; - CFDataRef asn1SignatureData = nil; - uint8_t mAsn1SignatureBytes[256]; - chip::MutableByteSpan asn1SignatureByteSpan = chip::MutableByteSpan(mAsn1SignatureBytes, sizeof(mAsn1SignatureBytes)); - CFErrorRef error = nil; - size_t signatureLen = 0; - - do { - dataToSign = CFDataCreate(CFAllocatorGetDefault(), messageToSign.data(), messageToSign.size()); - if (nil == dataToSign) { - ChipLogError( - AppServer, "DeviceAttestationCredentialsProviderImpl::SignWithDeviceAttestationKey failed to create buffer"); - result = CHIP_ERROR_NO_MEMORY; - break; - } - - asn1SignatureData = SecKeyCreateSignature( - mDeviceAttestationCertPrivateKeyRef, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, dataToSign, &error); - if (nil != error || nil == asn1SignatureData) { - ChipLogError(AppServer, - "DeviceAttestationCredentialsProviderImpl::SignWithDeviceAttestationKey failed to sign the message. error = %lu", - CFErrorGetCode(error)); - result = CHIP_ERROR_INVALID_ARGUMENT; - break; - } - - signatureLen = CFDataGetLength(asn1SignatureData); - - CFDataGetBytes(asn1SignatureData, CFRangeMake(0, signatureLen), asn1SignatureByteSpan.data()); - asn1SignatureByteSpan.reduce_size(signatureLen); - - CHIP_ERROR conversionError = chip::Crypto::EcdsaAsn1SignatureToRaw( - 32, chip::ByteSpan(asn1SignatureByteSpan.data(), asn1SignatureByteSpan.size()), outSignatureBuffer); - if (CHIP_NO_ERROR != conversionError) { - ChipLogError(AppServer, - "DeviceAttestationCredentialsProviderImpl::SignWithDeviceAttestationKey failed to convert to raw signature."); - result = conversionError; - break; - } - } while (0); - - if (dataToSign != nil) { - CFRelease(dataToSign); - } - - if (asn1SignatureData != nil) { - CFRelease(asn1SignatureData); - } - - return result; -} diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h index ba9f40c24c519c..c5b791a05080d9 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCAttribute.h @@ -15,8 +15,6 @@ * limitations under the License. */ -#import "MCObserver.h" - #import #ifndef MCAttribute_h diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h index d01ce207519c4c..e796f25da609a0 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.h @@ -72,6 +72,8 @@ - (uint32_t)deviceType; - (bool)supportsCommissionerGeneratedPasscode; - (NSArray * _Nonnull)ipAddresses; +- (NSString * _Nonnull)hostName; +- (NSString * _Nonnull)instanceName; /** * @brief Returns the NSArray of MCEndpoints associated with this MCCastingPlayer diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index 3bc72235a86c72..1e94b77090e4c7 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -97,6 +97,20 @@ - (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Stro return self; } ++ (MCCastingPlayer * _Nullable)getTargetCastingPlayer +{ + ChipLogProgress(AppServer, "MCCastingPlayer.getTargetCastingPlayer called"); + VerifyOrReturnValue([[MCCastingApp getSharedInstance] isRunning], nil, ChipLogError(AppServer, "MCCastingApp NOT running")); + __block MCCastingPlayer * castingPlayer = nil; + dispatch_sync([[MCCastingApp getSharedInstance] getWorkQueue], ^{ + matter::casting::core::CastingPlayer * cppCastingPlayer = matter::casting::core::CastingPlayer::GetTargetCastingPlayer(); + if (cppCastingPlayer != nullptr) { + castingPlayer = [[MCCastingPlayer alloc] initWithCppCastingPlayer:std::make_shared(*cppCastingPlayer)]; + } + }); + return castingPlayer; +} + - (NSString * _Nonnull)description { return [NSString stringWithFormat:@"%@ with Product ID: %hu and Vendor ID: %hu. Resolved IPAddr?: %@. Supports Commissioner Generated Passcode?: %@.", @@ -133,6 +147,16 @@ - (bool)supportsCommissionerGeneratedPasscode return _cppCastingPlayer->GetSupportsCommissionerGeneratedPasscode(); } +- (NSString * _Nonnull)hostName +{ + return [NSString stringWithCString:_cppCastingPlayer->GetHostName() encoding:NSUTF8StringEncoding]; +} + +- (NSString * _Nonnull)instanceName +{ + return [NSString stringWithCString:_cppCastingPlayer->GetInstanceName() encoding:NSUTF8StringEncoding]; +} + - (NSArray * _Nonnull)ipAddresses { NSMutableArray * ipAddresses = [NSMutableArray new]; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayerDiscovery.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayerDiscovery.mm index b69817266c6edc..51379b77b56776 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayerDiscovery.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayerDiscovery.mm @@ -19,7 +19,7 @@ #import "MCCastingApp.h" -#import "MCCastingPlayer.mm" +#import "MCCastingPlayer_Internal.h" #import "MCErrorUtils.h" #include "core/CastingPlayer.h" diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h index 6c52733c3d6909..87f3da455abcd4 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer_Internal.h @@ -26,6 +26,8 @@ @interface MCCastingPlayer () ++ (MCCastingPlayer * _Nullable)getTargetCastingPlayer; + - (instancetype _Nonnull)initWithCppCastingPlayer:(matter::casting::memory::Strong)cppCastingPlayer; @end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.h index 00cbf0628ab9f8..8f2d3efc8aef47 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.h @@ -44,8 +44,7 @@ class MCDeviceAttestationCredentialsProvider : public chip::Credentials::DeviceA chip::MutableByteSpan & outSignatureBuffer) override; private: - id mDataSource = nullptr; - MCDeviceAttestationCredentials * mDac = nullptr; + id mDataSource = nullptr; }; }; // namespace support diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.mm index 16a49c76363792..3f1f155d782fa9 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCDeviceAttestationCredentialsProvider.mm @@ -33,24 +33,22 @@ { VerifyOrReturnError(dataSource != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(mDataSource == nullptr, CHIP_ERROR_INCORRECT_STATE); - mDataSource = dataSource; - mDac = [mDataSource - castingAppDidReceiveRequestForDeviceAttestationCredentials:@"MCDeviceAttestationCredentialsProvider.Initialize()"]; - return CHIP_NO_ERROR; } CHIP_ERROR MCDeviceAttestationCredentialsProvider::GetCertificationDeclaration( chip::MutableByteSpan & outCertificationDeclaration) { - VerifyOrReturnError(mDac != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDataSource != nullptr, CHIP_ERROR_INCORRECT_STATE); + MCDeviceAttestationCredentials * dac = [mDataSource + castingAppDidReceiveRequestForDeviceAttestationCredentials:@"MCDeviceAttestationCredentialsProvider.Initialize()"]; - if (mDac.certificationDeclaration != nullptr && mDac.certificationDeclaration.length > 0) { - if (outCertificationDeclaration.size() >= mDac.certificationDeclaration.length) { - memcpy(outCertificationDeclaration.data(), mDac.certificationDeclaration.bytes, - mDac.certificationDeclaration.length); - outCertificationDeclaration.reduce_size(mDac.certificationDeclaration.length); + if (dac.certificationDeclaration != nullptr && dac.certificationDeclaration.length > 0) { + if (outCertificationDeclaration.size() >= dac.certificationDeclaration.length) { + memcpy(outCertificationDeclaration.data(), dac.certificationDeclaration.bytes, + dac.certificationDeclaration.length); + outCertificationDeclaration.reduce_size(dac.certificationDeclaration.length); } else { return CHIP_ERROR_BUFFER_TOO_SMALL; } @@ -60,12 +58,14 @@ CHIP_ERROR MCDeviceAttestationCredentialsProvider::GetFirmwareInformation(chip::MutableByteSpan & outFirmwareInformation) { - VerifyOrReturnError(mDac != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDataSource != nullptr, CHIP_ERROR_INCORRECT_STATE); + MCDeviceAttestationCredentials * dac = [mDataSource + castingAppDidReceiveRequestForDeviceAttestationCredentials:@"MCDeviceAttestationCredentialsProvider.Initialize()"]; - if (mDac.firmwareInformation != nullptr && mDac.firmwareInformation.length > 0) { - if (outFirmwareInformation.size() >= mDac.firmwareInformation.length) { - memcpy(outFirmwareInformation.data(), mDac.firmwareInformation.bytes, mDac.firmwareInformation.length); - outFirmwareInformation.reduce_size(mDac.firmwareInformation.length); + if (dac.firmwareInformation != nullptr && dac.firmwareInformation.length > 0) { + if (outFirmwareInformation.size() >= dac.firmwareInformation.length) { + memcpy(outFirmwareInformation.data(), dac.firmwareInformation.bytes, dac.firmwareInformation.length); + outFirmwareInformation.reduce_size(dac.firmwareInformation.length); } else { return CHIP_ERROR_BUFFER_TOO_SMALL; } @@ -76,12 +76,14 @@ CHIP_ERROR MCDeviceAttestationCredentialsProvider::GetDeviceAttestationCert( chip::MutableByteSpan & outDeviceAttestationCert) { - VerifyOrReturnError(mDac != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDataSource != nullptr, CHIP_ERROR_INCORRECT_STATE); + MCDeviceAttestationCredentials * dac = [mDataSource + castingAppDidReceiveRequestForDeviceAttestationCredentials:@"MCDeviceAttestationCredentialsProvider.Initialize()"]; - if (mDac.deviceAttestationCert != nullptr && mDac.deviceAttestationCert.length > 0) { - if (outDeviceAttestationCert.size() >= mDac.deviceAttestationCert.length) { - memcpy(outDeviceAttestationCert.data(), mDac.deviceAttestationCert.bytes, mDac.deviceAttestationCert.length); - outDeviceAttestationCert.reduce_size(mDac.deviceAttestationCert.length); + if (dac.deviceAttestationCert != nullptr && dac.deviceAttestationCert.length > 0) { + if (outDeviceAttestationCert.size() >= dac.deviceAttestationCert.length) { + memcpy(outDeviceAttestationCert.data(), dac.deviceAttestationCert.bytes, dac.deviceAttestationCert.length); + outDeviceAttestationCert.reduce_size(dac.deviceAttestationCert.length); } else { return CHIP_ERROR_BUFFER_TOO_SMALL; } @@ -92,13 +94,15 @@ CHIP_ERROR MCDeviceAttestationCredentialsProvider::GetProductAttestationIntermediateCert( chip::MutableByteSpan & outProductAttestationIntermediateCert) { - VerifyOrReturnError(mDac != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDataSource != nullptr, CHIP_ERROR_INCORRECT_STATE); + MCDeviceAttestationCredentials * dac = [mDataSource + castingAppDidReceiveRequestForDeviceAttestationCredentials:@"MCDeviceAttestationCredentialsProvider.Initialize()"]; - if (mDac.productAttestationIntermediateCert != nullptr && mDac.productAttestationIntermediateCert.length > 0) { - if (outProductAttestationIntermediateCert.size() >= mDac.productAttestationIntermediateCert.length) { - memcpy(outProductAttestationIntermediateCert.data(), mDac.productAttestationIntermediateCert.bytes, - mDac.productAttestationIntermediateCert.length); - outProductAttestationIntermediateCert.reduce_size(mDac.productAttestationIntermediateCert.length); + if (dac.productAttestationIntermediateCert != nullptr && dac.productAttestationIntermediateCert.length > 0) { + if (outProductAttestationIntermediateCert.size() >= dac.productAttestationIntermediateCert.length) { + memcpy(outProductAttestationIntermediateCert.data(), dac.productAttestationIntermediateCert.bytes, + dac.productAttestationIntermediateCert.length); + outProductAttestationIntermediateCert.reduce_size(dac.productAttestationIntermediateCert.length); } else { return CHIP_ERROR_BUFFER_TOO_SMALL; } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h index d252bd3c92f3e1..db340f097764f4 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.h @@ -17,7 +17,7 @@ #import "MCCastingPlayer.h" #import "MCCluster.h" -#import "MCEndpointClusterType.h" +#import "zap-generated/MCEndpointClusterType.h" #import diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm index f5e5aac89abb69..76d1eaf70724f9 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm @@ -44,6 +44,18 @@ - (instancetype _Nonnull)initWithCppEndpoint:(matter::casting::memory::Strong cppServerList = _cppEndpoint->GetServerList(); + for (chip::ClusterId clusterId : cppServerList) { + [serverList addObject:@(clusterId)]; + } + } + return serverList; +} + - (NSNumber * _Nonnull)identifier { return [NSNumber numberWithUnsignedShort:_cppEndpoint->GetId()]; @@ -78,15 +90,27 @@ - (MCCastingPlayer * _Nonnull)castingPlayer - (MCCluster * _Nullable)clusterForType:(MCEndpointClusterType)type { switch (type) { + case MCEndpointClusterTypeApplicationBasic: + return [[MCApplicationBasicCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + + case MCEndpointClusterTypeApplicationLauncher: + return [[MCApplicationLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeContentLauncher: return [[MCContentLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; - case MCEndpointClusterTypeApplicationBasic: - return [[MCApplicationBasicCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeKeypadInput: + return [[MCKeypadInputCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; case MCEndpointClusterTypeMediaPlayback: return [[MCMediaPlaybackCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeOnOff: + return [[MCOnOffCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + + case MCEndpointClusterTypeTargetNavigator: + return [[MCTargetNavigatorCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + default: ChipLogError(AppServer, "MCEndpointClusterType not found"); break; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h index 53b1d6bf22218e..ac40932c8a170c 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint_Internal.h @@ -28,6 +28,8 @@ - (instancetype _Nonnull)initWithCppEndpoint:(matter::casting::memory::Strong)cppEndpoint; +- (NSMutableArray *)getServerList; + @end #endif /* MCEndpoint_Internal_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.h index 56606e96b7a7d9..4887fac865ddba 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.h @@ -34,6 +34,8 @@ + (NSError * _Nonnull)NSErrorFromMatterError:(MatterError * _Nonnull)matterError; ++ (MatterError * _Nonnull)MatterErrorFromNsError:(NSError * _Nonnull)nsError; + @end #endif /* MCErrorUtils_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.mm index 66fc7544aad226..e4616853fc76a2 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCErrorUtils.mm @@ -38,4 +38,8 @@ + (NSError * _Nonnull)NSErrorFromMatterError:(MatterError * _Nonnull)matterError return matterError == MATTER_NO_ERROR ? nil : [NSError errorWithDomain:@"com.matter.casting" code:matterError.code userInfo:@{ NSUnderlyingErrorKey : matterError.message }]; } ++ (MatterError * _Nonnull)MatterErrorFromNsError:(NSError * _Nonnull)nsError +{ + return nsError == nil ? MATTER_NO_ERROR : [[MatterError alloc] initWithCode:static_cast(nsError.code) message:nsError.userInfo[NSUnderlyingErrorKey]]; +} @end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterError.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterError.mm index cbee1a455a51ca..6d4a84c043a24e 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterError.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterError.mm @@ -23,7 +23,7 @@ @implementation MatterError -MatterError * MATTER_NO_ERROR = [[MatterError alloc] initWithCode:0 message:nil]; +MatterError * MATTER_NO_ERROR = [[MatterError alloc] initWithCode:0 message:@"No error"]; MatterError * MATTER_ERROR_INCORRECT_STATE = [[MatterError alloc] initWithCode:CHIP_ERROR_INCORRECT_STATE.AsInteger() diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h index 851b94606d628a..5e83cea90b0728 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MatterTvCastingBridge.h @@ -23,7 +23,7 @@ FOUNDATION_EXPORT double MatterTvCastingBridgeVersionNumber; //! Project version string for MatterTvCastingBridge. FOUNDATION_EXPORT const unsigned char MatterTvCastingBridgeVersionString[]; -#import "CastingServerBridge.h" +#import "compat-shim/CastingServerBridge.h" // Add simplified casting API headers here #import "MCAttribute.h" @@ -36,9 +36,9 @@ FOUNDATION_EXPORT const unsigned char MatterTvCastingBridgeVersionString[]; #import "MCCryptoUtils.h" #import "MCDataSource.h" #import "MCDeviceAttestationCredentials.h" -#import "MCEndpointClusterType.h" +#import "MCEndpoint.h" #import "MCEndpointFilter.h" -#import "MCObserver.h" #import "zap-generated/MCAttributeObjects.h" #import "zap-generated/MCClusterObjects.h" #import "zap-generated/MCCommandObjects.h" +#import "zap-generated/MCEndpointClusterType.h" diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/AppParameters.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/AppParameters.h similarity index 91% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/AppParameters.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/AppParameters.h index 34585289fb6d5c..e49b17c5dcf1ef 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/AppParameters.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/AppParameters.h @@ -23,6 +23,7 @@ #ifndef AppParameters_h #define AppParameters_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface AppParameters : NSObject @property NSData * rotatingDeviceIdUniqueId; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/AppParameters.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/AppParameters.mm similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/AppParameters.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/AppParameters.mm diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.h new file mode 100644 index 00000000000000..dda77fa585f612 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.h @@ -0,0 +1,34 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "DiscoveredNodeData.h" + +#import + +#ifndef CastingPlayerDiscoveryListenerCompat_h +#define CastingPlayerDiscoveryListenerCompat_h + +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) +@interface CastingPlayerDiscoveryListenerCompat : NSObject + ++ (void)addObservers:(dispatch_queue_t _Nonnull)clientQueue discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler; + ++ (void)removeObservers; + +@end + +#endif /* CastingPlayerDiscoveryListenerCompat_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.mm new file mode 100644 index 00000000000000..35216fd87cc248 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingPlayerDiscoveryListenerCompat.mm @@ -0,0 +1,134 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "CastingPlayerDiscoveryListenerCompat.h" + +#import "DiscoveredNodeData.h" +#import "MCCastingPlayer.h" +#import "MCCastingPlayerDiscovery.h" +#import "MCErrorUtils.h" + +#include + +@interface CastingPlayerDiscoveryListenerCompat () + +@property (class, nonatomic, strong) dispatch_queue_t clientQueue; +@property (class, nonatomic, copy, nullable) void (^discoveredCommissionerHandler)(DiscoveredNodeData * _Nullable); + ++ (void)didAddDiscoveredCastingPlayers:(NSNotification * _Nonnull)notification; ++ (void)didUpdateDiscoveredCastingPlayers:(NSNotification * _Nonnull)notification; + +@end + +@implementation CastingPlayerDiscoveryListenerCompat + +static dispatch_queue_t _clientQueue; +static void (^_discoveredCommissionerHandler)(DiscoveredNodeData * _Nullable); + ++ (dispatch_queue_t)clientQueue +{ + return _clientQueue; +} + ++ (void)setClientQueue:(dispatch_queue_t)clientQueue +{ + _clientQueue = clientQueue; +} + ++ (void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler +{ + return _discoveredCommissionerHandler; +} + ++ (void)setDiscoveredCommissionerHandler:(void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler +{ + _discoveredCommissionerHandler = discoveredCommissionerHandler; +} + ++ (void)addObservers:(dispatch_queue_t _Nonnull)clientQueue discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull __strong))discoveredCommissionerHandler +{ + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.addObservers() called"); + [self setClientQueue:clientQueue]; + [self setDiscoveredCommissionerHandler:discoveredCommissionerHandler]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didAddDiscoveredCastingPlayers:) + name:ADD_CASTING_PLAYER_NOTIFICATION_NAME + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didUpdateDiscoveredCastingPlayers:) + name:UPDATE_CASTING_PLAYER_NOTIFICATION_NAME + object:nil]; +} + ++ (void)removeObservers +{ + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.removeObservers() called"); + [[NSNotificationCenter defaultCenter] removeObserver:self + name:ADD_CASTING_PLAYER_NOTIFICATION_NAME + object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UPDATE_CASTING_PLAYER_NOTIFICATION_NAME + object:nil]; +} + ++ (void)didAddDiscoveredCastingPlayers:(NSNotification *)notification +{ + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.didAddDiscoveredCastingPlayers() called"); + VerifyOrReturn(CastingPlayerDiscoveryListenerCompat.clientQueue != nil); + VerifyOrReturn(CastingPlayerDiscoveryListenerCompat.discoveredCommissionerHandler != nil); + + NSDictionary * userInfo = notification.userInfo; + MCCastingPlayer * castingPlayer = userInfo[CASTING_PLAYER_KEY]; + + if (![castingPlayer isKindOfClass:[MCCastingPlayer class]]) { + ChipLogError(AppServer, "CastingPlayerDiscoveryListenerCompat.didAddDiscoveredCastingPlayers called with no MCCastingPlayer"); + return; + } + + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.didAddDiscoveredCastingPlayers notified of a MCCastingPlayer with ID: %@", [castingPlayer identifier]); + + DiscoveredNodeData * discoveredNodeData = [[DiscoveredNodeData alloc] initWithCastingPlayer:castingPlayer]; + dispatch_async(CastingPlayerDiscoveryListenerCompat.clientQueue, ^{ + CastingPlayerDiscoveryListenerCompat.discoveredCommissionerHandler(discoveredNodeData); + }); +} + ++ (void)didUpdateDiscoveredCastingPlayers:(NSNotification *)notification +{ + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.didUpdateDiscoveredCastingPlayers() called"); + VerifyOrReturn(CastingPlayerDiscoveryListenerCompat.clientQueue != nil); + VerifyOrReturn(CastingPlayerDiscoveryListenerCompat.discoveredCommissionerHandler != nil); + + NSDictionary * userInfo = notification.userInfo; + MCCastingPlayer * castingPlayer = userInfo[CASTING_PLAYER_KEY]; + + if (![castingPlayer isKindOfClass:[MCCastingPlayer class]]) { + ChipLogError(AppServer, "CastingPlayerDiscoveryListenerCompat.didUpdateDiscoveredCastingPlayers called with no MCCastingPlayer"); + return; + } + + ChipLogProgress(AppServer, "CastingPlayerDiscoveryListenerCompat.didUpdateDiscoveredCastingPlayers notified of a MCCastingPlayer with ID: %@", [castingPlayer identifier]); + + DiscoveredNodeData * discoveredNodeData = [[DiscoveredNodeData alloc] initWithCastingPlayer:castingPlayer]; + dispatch_async(CastingPlayerDiscoveryListenerCompat.clientQueue, ^{ + CastingPlayerDiscoveryListenerCompat.discoveredCommissionerHandler(discoveredNodeData); + }); +} + +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.h new file mode 100644 index 00000000000000..01682cd89e3d98 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.h @@ -0,0 +1,739 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "../MatterError.h" +#import "AppParameters.h" +#import "CommissioningCallbackHandlers.h" +#import "ContentApp.h" +#import "ContentLauncherTypes.h" +#import "DiscoveredNodeData.h" +#import "MediaPlaybackTypes.h" +#import "OnboardingPayload.h" +#import "TargetNavigatorTypes.h" +#import "VideoPlayer.h" +#import + +#ifndef CastingServerBridge_h +#define CastingServerBridge_h + +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) +@interface CastingServerBridge : NSObject + ++ (CastingServerBridge * _Nullable)getSharedInstance; + +- (MatterError * _Nonnull)initializeApp:(AppParameters * _Nullable)appParameters + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + initAppStatusHandler:(nullable void (^)(MatterError * _Nonnull))initAppStatusHandler; + +- (void)setDacHolder:(DeviceAttestationCredentialsHolder * _Nonnull)deviceAttestationCredentials + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + setDacHolderStatus:(void (^_Nonnull)(MatterError * _Nonnull))setDacHolderStatus; + +/*! + @brief Browse for on-network commissioner TVs + + @param clientQueue Queue to dispatch the call to the discoveryRequestSentHandler on + + @param timeoutInSeconds time after which this discovery request should be auto-canceled + + @param discoveryRequestSentHandler Handler to call after the Commissioner discovery request has been sent + */ +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + timeoutInSeconds:(NSUInteger)timeoutInSeconds + discoveryRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler; + +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + discoveryRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nonnull))discoveredCommissionerHandler; + +/*! + @brief Send a User Directed Commissioning request to a commissioner TV + + @param commissioner Commissioner to request commissioning from + + @param clientQueue Queue to dispatch the call to the udcRequestSentHandler on + + @param udcRequestSentHandler Handler to call on sending the User Directed Commissioning request + */ +- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))udcRequestSentHandler; + +/*! + @brief Send a User Directed Commissioning request to a commissioner TV + + @param commissioner Commissioner to request commissioning from + + @param clientQueue Queue to dispatch the call to the udcRequestSentHandler on + + @param udcRequestSentHandler Handler to call on sending the User Directed Commissioning request + + @param desiredContentAppVendorId VendorId of the ContentApp that the client wants to interact with / cast to. If this value is passed in, the CastingServerBridge will force User Directed + * Commissioning, in case the desired ContentApp is not found in the on-device cached information + */ +- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))udcRequestSentHandler + desiredContentAppVendorId:(uint16_t)desiredContentAppVendorId; + +/*! + @brief Return the onboarding payload for this app (setup passcode, discriminator) + + @return Onboarding payload + */ +- (OnboardingPayload * _Nonnull)getOnboardingPayload; + +/*! + @brief Request opening of a basic commissioning window + + @param clientQueue Queue to dispatch the call to the commissioningWindowRequestedHandler on + + @param commissioningCallbackHandlers Optional parameter to specific handlers for callbacks during commissioning + + @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established + + @param onConnectionFailureCallback Handles MatterError if there is a failure in establishing connection + + @param onNewOrUpdatedEndpointCallback Handles a ContentApp * for each new ContentApp is found. May be called multiple times based + on the number of ContentApp + */ +- (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue + commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; + +/*! + @brief Gets the list of VideoPlayers currently connected + + @param clientQueue Queue to invoke callbacks on + + @param activeTargetVideoPlayersHandler Handles NSMutableArray of active/currently connected VideoPlayers. Nil, if no such + VideoPlayers are found. + */ +- (void)getActiveTargetVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue + activeTargetVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))activeTargetVideoPlayersHandler; + +/*! + @brief Verify if a connection exists or connect to the VideoPlayer passed in as parameter. + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handles MatterError and called after the request has been sent + + @param onConnectionSuccessCallback Handles a VideoPlayer * once connection is successfully established + + @param onConnectionFailureCallback Handles MatterError if there is a failure in establishing connection + + @param onNewOrUpdatedEndpointCallback Handles a ContentApp * for each new ContentApp is found. May be called multiple times based + on the number of ContentApp + */ +- (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(nullable void (^)(MatterError * _Nonnull))requestSentHandler + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback; + +/*! + @brief Tears down all active subscriptions. + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Called after the request has been sent + */ +- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler; + +/*! + @brief Mark any open session with the currently connected Video player as expired. + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Called after the request has been sent + */ +- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler; + +/*! + @brief Purge data cached by the Matter casting library + + @param clientQueue Queue to invoke callbacks on + + @param responseHandler Called when purgeCache completes + */ +- (void)purgeCache:(dispatch_queue_t _Nonnull)clientQueue responseHandler:(void (^_Nonnull)(MatterError * _Nonnull))responseHandler; + +/*! + @brief Start the Matter server and reconnect to a previously connected Video Player (if any). This API is async + + @param clientQueue Queue to invoke callbacks on + + @param startMatterServerCompletionCallback Called after the Matter server has started and connected (or failed to connect) to a + previously connected video player (if any) are complete + */ +- (void)startMatterServer:(dispatch_queue_t _Nonnull)clientQueue + startMatterServerCompletionCallback:(nullable void (^)(MatterError * _Nonnull))startMatterServerCompletionCallback; + +/** + @brief Stop the Matter server + */ +- (void)stopMatterServer; + +/*! + @brief Send a ContentLauncher:LaunchURL request to a TV + + @param contentApp Content app endpoint to target + + @param contentUrl URL of the content to launch on the TV + + @param contentDisplayStr Display string value corresponding to the content + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)contentLauncher_launchUrl:(ContentApp * _Nonnull)contentApp + contentUrl:(NSString * _Nonnull)contentUrl + contentDisplayStr:(NSString * _Nonnull)contentDisplayStr + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a ContentLauncher:LaunchContent request to a TV + + @param contentApp Content app endpoint to target + + @param contentSearch Indicates the content to launch + + @param autoPlay Play Best match automatically if true, otherwise display matches + + @param data App specific data to be passed to the TV + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)contentLauncher_launchContent:(ContentApp * _Nonnull)contentApp + contentSearch:(ContentLauncher_ContentSearch * _Nonnull)contentSearch + autoPlay:(bool)autoPlay + data:(NSString * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Play request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_play:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Pause request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_pause:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:StopPlayback request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_stopPlayback:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Next request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_next:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Previous request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_previous:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:FastForward request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_fastForward:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Rewind request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_rewind:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:StartOver request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_startOver:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:Seek request to a TV + + @param contentApp Content app endpoint to target + + @param position the position (in milliseconds) in the media to seek to + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_seek:(ContentApp * _Nonnull)contentApp + position:(uint64_t)position + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:SkipForward request to a TV + + @param contentApp Content app endpoint to target + + @param deltaPositionMilliseconds the duration of the time span to skip forward in the media, in milliseconds + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_skipForward:(ContentApp * _Nonnull)contentApp + deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a MediaPlayback:SkipBackward request to a TV + + @param contentApp Content app endpoint to target + + @param deltaPositionMilliseconds the duration of the time span to skip backward in the media, in milliseconds + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)mediaPlayback_skipBackward:(ContentApp * _Nonnull)contentApp + deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Subscribe to MediaPlayback:CurrentState + + @param contentApp Content app endpoint to target + + @param minInterval Minimum interval between attribute read reports + + @param maxInterval Maximum interval between attribute read reports + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + + @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully + */ +- (void)mediaPlayback_subscribeCurrentState:(ContentApp * _Nonnull)contentApp + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackState))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback + subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; + +/*! + @brief Send a ApplicationLauncher:LaunchApp request to a TV + + @param contentApp Content app endpoint to target + + @param catalogVendorId CSA-issued vendor ID for the catalog + + @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" + + @param data optional app-specific data to be sent to the app + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)applicationLauncher_launchApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + data:(NSData * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a ApplicationLauncher:StopApp request to a TV + + @param contentApp Content app endpoint to target + + @param catalogVendorId CSA-issued vendor ID for the catalog + + @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)applicationLauncher_stopApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a ApplicationLauncher:HideApp request to a TV + + @param contentApp Content app endpoint to target + + @param catalogVendorId CSA-issued vendor ID for the catalog + + @param applicationId application identifier, unique within a catalog, expressed as a string, such as "PruneVideo" or "Company X" + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)applicationLauncher_hideApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a TargetNavigator:NavigateTarget request to a TV + + @param contentApp Content app endpoint to target + + @param target Identifier for the target for UX navigation, contained within one of the TargetInfo objects in the TargetList + attribute list. + + @param data Optional app-specific data + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)targetNavigator_navigateTarget:(ContentApp * _Nonnull)contentApp + target:(uint8_t)target + data:(NSString * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Subscribe to TargetNavigator:TargetList + + @param contentApp Content app endpoint to target + + @param minInterval Minimum interval between attribute read reports + + @param maxInterval Maximum interval between attribute read reports + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + + @param subscriptionEstablishedCallback Callback for when the requested subscription has been established successfully + */ +- (void)targetNavigator_subscribeTargetList:(ContentApp * _Nonnull)contentApp + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSMutableArray * _Nullable))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback + subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback; + +/*! + @brief Send a KeypadInput:SendKey request to a TV + + @param contentApp Content app endpoint to target + + @param keyCode Key Code to process. If a second SendKey request with the same KeyCode value is received within 200ms, then the + endpoint will consider the first key press to be a press and hold. When such a repeat KeyCode value is not received within 200ms, + then the endpoint will consider the last key press to be a release. + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)keypadInput_sendKey:(ContentApp * _Nonnull)contentApp + keyCode:(uint8_t)keyCode + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Read ApplicationBasic:VendorName + + @param contentApp Content app endpoint to target + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + */ +- (void)applicationBasic_readVendorName:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; + +/*! + @brief Read ApplicationBasic:VendorID + + @param contentApp Content app endpoint to target + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + */ +- (void)applicationBasic_readVendorID:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; + +/*! + @brief Read ApplicationBasic:ApplicationName + + @param contentApp Content app endpoint to target + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + */ +- (void)applicationBasic_readApplicationName:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; + +/*! + @brief Read ApplicationBasic:ProductID + + @param contentApp Content app endpoint to target + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + */ +- (void)applicationBasic_readProductID:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(uint16_t))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; + +/*! + @brief Read ApplicationBasic:ApplicationVersion + + @param contentApp Content app endpoint to target + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + + @param successCallback Callback for when a read report is successfully received + + @param failureCallback Callback for when there is a failure in receiving a read report + */ +- (void)applicationBasic_readApplicationVersion:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback; +/*! + @brief Send a OnOff:On request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_on:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a OnOff:Off request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_off:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; + +/*! + @brief Send a OnOff:Toggle request to a TV + + @param contentApp Content app endpoint to target + + @param responseCallback Callback for when the response has been received + + @param clientQueue Queue to invoke callbacks on + + @param requestSentHandler Handler to call on sending the request + */ +- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler; +@end +#endif /* CastingServerBridge_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.mm new file mode 100644 index 00000000000000..ca7ccb3162fa8c --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CastingServerBridge.mm @@ -0,0 +1,1290 @@ +/** + * + * Copyright (c) 2020-2023 Project CHIP Authors + * + * 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. + */ + +#import "CastingServerBridge.h" + +#import "../zap-generated/MCClusterObjects.h" +#import "../zap-generated/MCEndpointClusterType.h" +#import "CastingPlayerDiscoveryListenerCompat.h" +#import "DataSourceCompat.h" +#import "MCCastingApp.h" +#import "MCCastingPlayerDiscovery.h" +#import "MCCastingPlayer_Internal.h" +#import "MCEndpoint.h" +#import "MCErrorUtils.h" + +#import "MatterCallbacks.h" +#import "OnboardingPayload.h" + +#include +#include +#include +#include +#include +#include + +static const uint32_t kTargetPlayerDeviceType = 0x23; + +@interface CastingServerBridge () + +@property DataSourceCompat * dataSource; +@property dispatch_block_t cancelDiscoveryCommissionersWork; +@property dispatch_queue_t commissioningClientQueue; +@property CommissioningCallbackHandlers * commissioningCallbackHandlers; +@property void (^_Nonnull onConnectionSuccessCallback)(VideoPlayer * _Nonnull); +@property void (^_Nonnull onConnectionFailureCallback)(MatterError * _Nonnull); +@property void (^_Nonnull onNewOrUpdatedEndpointCallback)(ContentApp * _Nonnull); +@property AppParameters * appParameters; ++ (MCCluster * _Nullable)getClusterWith:(MCEndpointClusterType)type contentApp:(ContentApp * _Nonnull)contentApp; + +@end + +@implementation CastingServerBridge + ++ (CastingServerBridge * _Nullable)getSharedInstance +{ + static CastingServerBridge * instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + ++ (MCCluster * _Nullable)getClusterWith:(MCEndpointClusterType)type contentApp:(ContentApp * _Nonnull)contentApp +{ + MCCastingPlayer * castingPlayer = [MCCastingPlayer getTargetCastingPlayer]; + VerifyOrReturnValue(castingPlayer != nil, nil, ChipLogError(AppServer, "CastingServerBridge.clusterForType no active target CastingPlayer found")); + + MCEndpoint * endpoint = [[castingPlayer endpoints] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(MCEndpoint * evalEndpoint, NSDictionary * bindings) { + return [[evalEndpoint identifier] intValue] == contentApp.endpointId; + }]].firstObject; + + VerifyOrReturnValue(endpoint != nil, nil, ChipLogError(AppServer, "CastingServerBridge.clusterForType endpoint with ID: %d not found", contentApp.endpointId)); + return [endpoint clusterForType:type]; +} + +- (MatterError *)initializeApp:(AppParameters * _Nullable)appParameters + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + initAppStatusHandler:(nullable void (^)(MatterError * _Nonnull))initAppStatusHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().initializeApp() called"); + + _appParameters = appParameters; + _dataSource = [[DataSourceCompat alloc] initWithClientQueue:clientQueue]; + [_dataSource setAppParameters:appParameters]; + + NSError * err = [MCCastingApp.getSharedInstance initializeWithDataSource:_dataSource]; + VerifyOrReturnValue(err == nil, [MCErrorUtils MatterErrorFromNsError:err]); + + [MCCastingApp.getSharedInstance startWithCompletionBlock:^(NSError * _Nullable e) { + dispatch_async(clientQueue, ^{ + initAppStatusHandler([MCErrorUtils MatterErrorFromNsError:e]); + }); + }]; + + return MATTER_NO_ERROR; +} + +- (void)setDacHolder:(DeviceAttestationCredentialsHolder * _Nonnull)deviceAttestationCredentials + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + setDacHolderStatus:(void (^_Nonnull)(MatterError * _Nonnull))setDacHolderStatus +{ + ChipLogProgress(AppServer, "CastingServerBridge().setDacHolder() called"); + + dispatch_sync([MCCastingApp.getSharedInstance getWorkQueue], ^{ + [self.dataSource setDacHolder:deviceAttestationCredentials]; + dispatch_async(clientQueue, ^{ + setDacHolderStatus(MATTER_NO_ERROR); + }); + }); +} + +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + discoveryRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData *))discoveredCommissionerHandler +{ + [self discoverCommissioners:clientQueue timeoutInSeconds:0 discoveryRequestSentHandler:discoveryRequestSentHandler discoveredCommissionerHandler:discoveredCommissionerHandler]; +} + +- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue + timeoutInSeconds:(NSUInteger)timeoutInSeconds + discoveryRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))discoveryRequestSentHandler + discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData *))discoveredCommissionerHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() called with timeoutInSeconds: %lu", timeoutInSeconds); + + dispatch_sync([[MCCastingApp getSharedInstance] getWorkQueue], ^{ + // cancel any future dispatches to cancelDiscoveryCommissionersWork + if (self->_cancelDiscoveryCommissionersWork) { + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() canceling dispatch to cancelDiscoveryCommissionersWork"); + dispatch_block_cancel(self->_cancelDiscoveryCommissionersWork); + self->_cancelDiscoveryCommissionersWork = nil; + } + }); + + // stop previously triggered discovery and remove observers, if any + NSError * e = [MCCastingPlayerDiscovery.sharedInstance stop]; + if (e != nil) { + ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() MCCastingPlayerDiscovery stop error: %@", e.description); + } + [CastingPlayerDiscoveryListenerCompat removeObservers]; + + // add observers and start discovery + [CastingPlayerDiscoveryListenerCompat addObservers:clientQueue discoveredCommissionerHandler:discoveredCommissionerHandler]; + NSError * err = [MCCastingPlayerDiscovery.sharedInstance start:kTargetPlayerDeviceType]; + if (err == nil) { + // if positive timeoutInSeconds specified, dispatch call to cancel this discovery request AFTER timeoutInSeconds + if (timeoutInSeconds > 0) { + self->_cancelDiscoveryCommissionersWork + = dispatch_block_create(static_cast(0), ^{ + if (dispatch_block_testcancel(self->_cancelDiscoveryCommissionersWork)) { + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() cancel timer invalidated."); + return; + } + + // stop previously triggered discovery and remove observers, if any + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() canceling previous discovery request"); + NSError * e = [MCCastingPlayerDiscovery.sharedInstance stop]; + if (e != nil) { + ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() MCCastingPlayerDiscovery stop error: %@", e.description); + } + [CastingPlayerDiscoveryListenerCompat removeObservers]; + self->_cancelDiscoveryCommissionersWork = nil; + }); + + ChipLogProgress(AppServer, "CastingServerBridge().discoverCommissioners() dispatching cancelDiscoveryCommissionersWork for %lu sec later", timeoutInSeconds); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeoutInSeconds * NSEC_PER_SEC), [[MCCastingApp getSharedInstance] getWorkQueue], self->_cancelDiscoveryCommissionersWork); + } + } else { + ChipLogError(AppServer, "CastingServerBridge().discoverCommissioners() MCCastingPlayerDiscovery start error: %@", err.description); + [CastingPlayerDiscoveryListenerCompat removeObservers]; + } + + dispatch_async(clientQueue, ^{ + discoveryRequestSentHandler([MCErrorUtils MatterErrorFromNsError:err]); + }); +} + +- (OnboardingPayload *)getOnboardingPayload +{ + return _appParameters.onboardingPayload; +} + +- (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue + commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().openBasicCommissioningWindow() called"); + // capture the callbacks + _commissioningClientQueue = clientQueue; + _commissioningCallbackHandlers = commissioningCallbackHandlers; + _onConnectionSuccessCallback = onConnectionSuccessCallback; + _onConnectionFailureCallback = onConnectionFailureCallback; + _onNewOrUpdatedEndpointCallback = onNewOrUpdatedEndpointCallback; + + // no-op: short-circuit commissioningWindow callbacks with MATTER_NO_ERROR + dispatch_async(clientQueue, ^{ + if (commissioningCallbackHandlers != nil) { + if (commissioningCallbackHandlers.commissioningWindowRequestedHandler != nil) { + commissioningCallbackHandlers.commissioningWindowRequestedHandler(MATTER_NO_ERROR); + } + if (commissioningCallbackHandlers.commissioningWindowOpenedCallback != nil) { + commissioningCallbackHandlers.commissioningWindowOpenedCallback(MATTER_NO_ERROR); + } + } + }); +} + +- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))udcRequestSentHandler +{ + [self sendUserDirectedCommissioningRequest:commissioner clientQueue:clientQueue udcRequestSentHandler:udcRequestSentHandler]; +} + +- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + udcRequestSentHandler:(nullable void (^)(MatterError * _Nonnull))udcRequestSentHandler + desiredContentAppVendorId:(uint16_t)desiredContentAppVendorId +{ + ChipLogProgress(AppServer, "CastingServerBridge().sendUserDirectedCommissioningRequest() called with desiredContentAppVendorId: %d", desiredContentAppVendorId); + + MCEndpointFilter * filter = [MCEndpointFilter new]; + filter.vendorId = desiredContentAppVendorId; + + [commissioner.getCastingPlayer verifyOrEstablishConnectionWithCompletionBlock:^(NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err == nil) { + if (self->_commissioningCallbackHandlers != nil && self->_commissioningCallbackHandlers.commissioningCompleteCallback != nil) { + self->_commissioningCallbackHandlers.commissioningCompleteCallback(MATTER_NO_ERROR); + } + + MCCastingPlayer * castingPlayer = [MCCastingPlayer getTargetCastingPlayer]; + if (self->_onConnectionSuccessCallback != nil) { + self->_onConnectionSuccessCallback([[VideoPlayer alloc] initWithCastingPlayer:castingPlayer]); + } + + if (self->_onNewOrUpdatedEndpointCallback != nil && castingPlayer != nil) { + NSArray * endpoints = castingPlayer.endpoints; + for (MCEndpoint * endpoint in endpoints) { + self->_onNewOrUpdatedEndpointCallback([[ContentApp alloc] initWithEndpoint:endpoint]); + } + } + } + }); + } desiredEndpointFilter:filter]; + + dispatch_async(clientQueue, ^{ + udcRequestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)getActiveTargetVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue + activeTargetVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))activeTargetVideoPlayersHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().getActiveTargetVideoPlayers() called"); + NSMutableArray * videoPlayers = [NSMutableArray new]; + MCCastingPlayer * castingPlayer = [MCCastingPlayer getTargetCastingPlayer]; + if (castingPlayer != nil) { + VideoPlayer * videoPlayer = [[VideoPlayer alloc] initWithCastingPlayer:castingPlayer]; + videoPlayer.isConnected = true; + videoPlayers[0] = videoPlayer; + } + dispatch_async(clientQueue, ^{ + activeTargetVideoPlayersHandler(videoPlayers); + }); +} + +- (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(nullable void (^)(MatterError * _Nonnull))requestSentHandler + onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback + onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback + onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().verifyOrEstablishConnection() is unsupported"); + + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_NOT_IMPLEMENTED]); + }); +} + +- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().shutdownAllSubscriptions() called"); + [[MCCastingApp getSharedInstance] ShutdownAllSubscriptions]; + dispatch_async(clientQueue, ^{ + requestSentHandler(); + }); +} + +- (void)startMatterServer:(dispatch_queue_t _Nonnull)clientQueue + startMatterServerCompletionCallback:(nullable void (^)(MatterError * _Nonnull))startMatterServerCompletionCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().startMatterServer() called"); + [[MCCastingApp getSharedInstance] startWithCompletionBlock:^(NSError * _Nullable err) { + ChipLogError(AppServer, "CastingServerBridge() startWithCompletionBlock called"); + startMatterServerCompletionCallback([MCErrorUtils MatterErrorFromNsError:err]); + }]; +} + +- (void)stopMatterServer +{ + ChipLogProgress(AppServer, "CastingServerBridge().stopMatterServer() called"); + [[MCCastingApp getSharedInstance] stopWithCompletionBlock:^(NSError * _Nullable) { + ChipLogError(AppServer, "CastingServerBridge() stopWithCompletionBlock called"); + }]; +} + +- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().disconnect() called"); + MCCastingPlayer * castingPlayer = [MCCastingPlayer getTargetCastingPlayer]; + if (castingPlayer != nil) { + [castingPlayer disconnect]; + } + dispatch_async(clientQueue, ^{ + requestSentHandler(); + }); +} + +- (void)purgeCache:(dispatch_queue_t _Nonnull)clientQueue responseHandler:(void (^)(MatterError * _Nonnull))responseHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().purgeCache() called"); + NSError * err = [[MCCastingApp getSharedInstance] ClearCache]; + dispatch_async(clientQueue, ^{ + responseHandler([MCErrorUtils MatterErrorFromNsError:err]); + }); +} + +- (void)contentLauncher_launchUrl:(ContentApp * _Nonnull)contentApp + contentUrl:(NSString * _Nonnull)contentUrl + contentDisplayStr:(NSString * _Nonnull)contentDisplayStr + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().contentLauncher_launchUrl() called"); + MCContentLauncherCluster * cluster = (MCContentLauncherCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeContentLauncher contentApp:contentApp]; + if (cluster == nil || [cluster launchURLCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCContentLauncherClusterLaunchURLParams * request = [[MCContentLauncherClusterLaunchURLParams alloc] init]; + request.contentURL = contentUrl; + request.displayString = contentDisplayStr; + [[cluster launchURLCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCContentLauncherClusterLauncherResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)contentLauncher_launchContent:(ContentApp * _Nonnull)contentApp + contentSearch:(ContentLauncher_ContentSearch * _Nonnull)contentSearch + autoPlay:(bool)autoPlay + data:(NSString * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().contentLauncher_launchContent() called"); + MCContentLauncherCluster * cluster = (MCContentLauncherCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeContentLauncher contentApp:contentApp]; + if (cluster == nil || [cluster launchContentCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCContentLauncherClusterLaunchContentParams * request = [MCContentLauncherClusterLaunchContentParams new]; + request.autoPlay = @(autoPlay); + request.data = data; + MCContentLauncherClusterContentSearchStruct * search = nil; + if (contentSearch.parameterList != nil) { + NSMutableArray * parameterList = [NSMutableArray new]; + for (ContentLauncher_Parameter * srcParameter in contentSearch.parameterList) { + MCContentLauncherClusterParameterStruct * parameter = [MCContentLauncherClusterParameterStruct new]; + parameter.type = @(srcParameter.type); + parameter.value = srcParameter.value; + if (srcParameter.externalIDList != nil) { + NSMutableArray * externalIdList = [NSMutableArray new]; + for (ContentLauncher_AdditionalInfo * srcExternalId in srcParameter.externalIDList) { + MCContentLauncherClusterAdditionalInfoStruct * externalId = [MCContentLauncherClusterAdditionalInfoStruct new]; + externalId.name = srcExternalId.name; + externalId.value = srcExternalId.value; + [externalIdList addObject:externalId]; + } + parameter.externalIDList = externalIdList; + } + [parameterList addObject:parameter]; + } + + search = [MCContentLauncherClusterContentSearchStruct new]; + search.parameterList = parameterList; + } + request.search = search; + + [[cluster launchContentCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCContentLauncherClusterLauncherResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_play:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_play() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster playCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterPlayParams * request = [MCMediaPlaybackClusterPlayParams new]; + [[cluster playCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_pause:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_pause() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster pauseCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterPauseParams * request = [MCMediaPlaybackClusterPauseParams new]; + [[cluster pauseCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_stopPlayback:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_stopPlayback() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster stopCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterStopParams * request = [MCMediaPlaybackClusterStopParams new]; + [[cluster stopCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_next:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_next() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster nextCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterNextParams * request = [MCMediaPlaybackClusterNextParams new]; + [[cluster nextCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_seek:(ContentApp * _Nonnull)contentApp + position:(uint64_t)position + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_seek() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster seekCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterSeekParams * request = [MCMediaPlaybackClusterSeekParams new]; + request.position = @(position); + [[cluster seekCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_skipForward:(ContentApp * _Nonnull)contentApp + deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_skipForward() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster skipForwardCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterSkipForwardParams * request = [MCMediaPlaybackClusterSkipForwardParams new]; + request.deltaPositionMilliseconds = @(deltaPositionMilliseconds); + [[cluster skipForwardCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_skipBackward:(ContentApp * _Nonnull)contentApp + deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_skipBackward() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster skipBackwardCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterSkipBackwardParams * request = [MCMediaPlaybackClusterSkipBackwardParams new]; + request.deltaPositionMilliseconds = @(deltaPositionMilliseconds); + [[cluster skipBackwardCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_previous:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_previous() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster previousCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterPreviousParams * request = [MCMediaPlaybackClusterPreviousParams new]; + [[cluster previousCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_rewind:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_rewind() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster rewindCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterRewindParams * request = [MCMediaPlaybackClusterRewindParams new]; + [[cluster rewindCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_fastForward:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_fastForward() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster fastForwardCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterFastForwardParams * request = [MCMediaPlaybackClusterFastForwardParams new]; + [[cluster fastForwardCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_startOver:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_startOver() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster startOverCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCMediaPlaybackClusterStartOverParams * request = [MCMediaPlaybackClusterStartOverParams new]; + [[cluster startOverCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCMediaPlaybackClusterPlaybackResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)mediaPlayback_subscribeCurrentState:(ContentApp * _Nonnull)contentApp + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackState))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback + subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_subscribeCurrentState() called"); + MCMediaPlaybackCluster * cluster = (MCMediaPlaybackCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeMediaPlayback contentApp:contentApp]; + if (cluster == nil || [cluster currentStateAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster currentStateAttribute] subscribe:nil completion:^(void * _Nullable context, NSNumber * _Nullable before, NSNumber * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback((MediaPlayback_PlaybackState)[after unsignedCharValue]); + } + }); + } minInterval:@(minInterval) maxInterval:@(maxInterval)]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + subscriptionEstablishedCallback(); + }); +} + +- (void)applicationLauncher_launchApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + data:(NSData * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_launchApp() called"); + MCApplicationLauncherCluster * cluster = (MCApplicationLauncherCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationLauncher contentApp:contentApp]; + if (cluster == nil || [cluster launchAppCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCApplicationLauncherClusterLaunchAppParams * request = [MCApplicationLauncherClusterLaunchAppParams new]; + request.data = data; + MCApplicationLauncherClusterApplicationStruct * application = [MCApplicationLauncherClusterApplicationStruct new]; + application.catalogVendorID = @(catalogVendorId); + application.applicationID = applicationId; + request.application = application; + + [[cluster launchAppCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCApplicationLauncherClusterLauncherResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationLauncher_stopApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_stopApp() called"); + MCApplicationLauncherCluster * cluster = (MCApplicationLauncherCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationLauncher contentApp:contentApp]; + if (cluster == nil || [cluster stopAppCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCApplicationLauncherClusterStopAppParams * request = [MCApplicationLauncherClusterStopAppParams new]; + MCApplicationLauncherClusterApplicationStruct * application = [MCApplicationLauncherClusterApplicationStruct new]; + application.catalogVendorID = @(catalogVendorId); + application.applicationID = applicationId; + request.application = application; + + [[cluster stopAppCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCApplicationLauncherClusterLauncherResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationLauncher_hideApp:(ContentApp * _Nonnull)contentApp + catalogVendorId:(uint16_t)catalogVendorId + applicationId:(NSString * _Nonnull)applicationId + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationLauncher_hideApp() called"); + MCApplicationLauncherCluster * cluster = (MCApplicationLauncherCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationLauncher contentApp:contentApp]; + if (cluster == nil || [cluster hideAppCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCApplicationLauncherClusterHideAppParams * request = [MCApplicationLauncherClusterHideAppParams new]; + MCApplicationLauncherClusterApplicationStruct * application = [MCApplicationLauncherClusterApplicationStruct new]; + application.catalogVendorID = @(catalogVendorId); + application.applicationID = applicationId; + request.application = application; + + [[cluster hideAppCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCApplicationLauncherClusterLauncherResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)targetNavigator_navigateTarget:(ContentApp * _Nonnull)contentApp + target:(uint8_t)target + data:(NSString * _Nullable)data + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().targetNavigator_navigateTarget() called"); + MCTargetNavigatorCluster * cluster = (MCTargetNavigatorCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeTargetNavigator contentApp:contentApp]; + if (cluster == nil || [cluster navigateTargetCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCTargetNavigatorClusterNavigateTargetParams * request = [MCTargetNavigatorClusterNavigateTargetParams new]; + request.target = @(target); + request.data = data; + + [[cluster navigateTargetCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCTargetNavigatorClusterNavigateTargetResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)targetNavigator_subscribeTargetList:(ContentApp * _Nonnull)contentApp + minInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSMutableArray *))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback + subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().targetNavigator_subscribeTargetList() called"); + MCTargetNavigatorCluster * cluster = (MCTargetNavigatorCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeTargetNavigator contentApp:contentApp]; + if (cluster == nil || [cluster targetListAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster targetListAttribute] subscribe:nil completion:^(void * _Nullable context, NSArray * _Nullable, NSArray * _Nullable newTargetList, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + NSMutableArray * resultTargetList = nil; + if (newTargetList != nil) { + resultTargetList = [NSMutableArray arrayWithCapacity:newTargetList.count]; + for (MCTargetNavigatorClusterTargetInfoStruct * targetInfo in newTargetList) { + [resultTargetList addObject:[[TargetNavigator_TargetInfoStruct alloc] initWithIdentifier:targetInfo.identifier name:targetInfo.name]]; + } + } + successCallback(resultTargetList); + } + }); + } minInterval:@(minInterval) maxInterval:@(maxInterval)]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + subscriptionEstablishedCallback(); + }); +} + +- (void)keypadInput_sendKey:(ContentApp * _Nonnull)contentApp + keyCode:(uint8_t)keyCode + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().keypadInput_sendKey() called"); + MCKeypadInputCluster * cluster = (MCKeypadInputCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeKeypadInput contentApp:contentApp]; + if (cluster == nil || [cluster sendKeyCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCKeypadInputClusterSendKeyParams * request = [MCKeypadInputClusterSendKeyParams new]; + request.keyCode = @(keyCode); + + [[cluster sendKeyCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCKeypadInputClusterSendKeyResponseParams * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationBasic_readVendorName:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readVendorName() called"); + MCApplicationBasicCluster * cluster = (MCApplicationBasicCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationBasic contentApp:contentApp]; + if (cluster == nil || [cluster vendorNameAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster vendorNameAttribute] read:nil completion:^(void * _Nullable context, NSString * _Nullable before, NSString * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback(after); + } + }); + }]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationBasic_readVendorID:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readVendorID() called"); + MCApplicationBasicCluster * cluster = (MCApplicationBasicCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationBasic contentApp:contentApp]; + if (cluster == nil || [cluster vendorIDAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster vendorIDAttribute] read:nil completion:^(void * _Nullable context, NSNumber * _Nullable before, NSNumber * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback(after); + } + }); + }]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationBasic_readApplicationName:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readApplicationName() called"); + MCApplicationBasicCluster * cluster = (MCApplicationBasicCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationBasic contentApp:contentApp]; + if (cluster == nil || [cluster applicationNameAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster applicationNameAttribute] read:nil completion:^(void * _Nullable context, NSString * _Nullable before, NSString * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback(after); + } + }); + }]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationBasic_readProductID:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(uint16_t))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readProductID() called"); + MCApplicationBasicCluster * cluster = (MCApplicationBasicCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationBasic contentApp:contentApp]; + if (cluster == nil || [cluster productIDAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster productIDAttribute] read:nil completion:^(void * _Nullable context, NSNumber * _Nullable before, NSNumber * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback([after unsignedShortValue]); + } + }); + }]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)applicationBasic_readApplicationVersion:(ContentApp * _Nonnull)contentApp + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler + successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback + failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback +{ + ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readApplicationVersion() called"); + MCApplicationBasicCluster * cluster = (MCApplicationBasicCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeApplicationBasic contentApp:contentApp]; + if (cluster == nil || [cluster applicationVersionAttribute] == nil) { + ChipLogError(AppServer, "Cluster/attribute not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + [[cluster applicationVersionAttribute] read:nil completion:^(void * _Nullable context, NSString * _Nullable before, NSString * _Nullable after, NSError * _Nullable err) { + dispatch_async(clientQueue, ^{ + if (err != nil) { + failureCallback([MCErrorUtils MatterErrorFromNsError:err]); + } else { + successCallback(after); + } + }); + }]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)onOff_on:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().onOff_on() called"); + MCOnOffCluster * cluster = (MCOnOffCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeOnOff contentApp:contentApp]; + if (cluster == nil || [cluster onCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCOnOffClusterOnParams * request = [MCOnOffClusterOnParams new]; + [[cluster onCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCNullObjectType * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)onOff_off:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().onOff_off() called"); + MCOnOffCluster * cluster = (MCOnOffCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeOnOff contentApp:contentApp]; + if (cluster == nil || [cluster offCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCOnOffClusterOffParams * request = [MCOnOffClusterOffParams new]; + [[cluster offCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCNullObjectType * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} + +- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp + responseCallback:(void (^_Nonnull)(MatterError * _Nonnull))responseCallback + clientQueue:(dispatch_queue_t _Nonnull)clientQueue + requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler +{ + ChipLogProgress(AppServer, "CastingServerBridge().onOff_toggle() called"); + MCOnOffCluster * cluster = (MCOnOffCluster *) [CastingServerBridge getClusterWith:MCEndpointClusterTypeOnOff contentApp:contentApp]; + if (cluster == nil || [cluster toggleCommand] == nil) { + ChipLogError(AppServer, "Cluster/command not found"); + dispatch_async(clientQueue, ^{ + requestSentHandler([MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]); + }); + return; + } + + // create request + MCOnOffClusterToggleParams * request = [MCOnOffClusterToggleParams new]; + [[cluster toggleCommand] invoke:request + context:nil + completion:^(void * _Nullable, NSError * _Nullable err, MCNullObjectType * _Nullable response) { + dispatch_async(clientQueue, ^{ + responseCallback([MCErrorUtils MatterErrorFromNsError:err]); + }); + } + timedInvokeTimeoutMs:@5000]; + + dispatch_async(clientQueue, ^{ + requestSentHandler(MATTER_NO_ERROR); + }); +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.h similarity index 83% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.h index 14288d7ffd6234..0b8abce46c2d61 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.h @@ -15,17 +15,19 @@ * limitations under the License. */ -#import "MatterError.h" +#import "../MatterError.h" #import #ifndef CommissioningCallbacksHandlers_h #define CommissioningCallbacksHandlers_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface CommissioningCallbackHandlers : NSObject - (CommissioningCallbackHandlers * _Nonnull) - initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler - commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback + initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(MatterError * _Nonnull))commissioningWindowRequestedHandler + commissioningWindowOpenedCallback:(void (^_Nonnull)(MatterError * _Nonnull))commissioningWindowOpenedCallback + commissioningCompleteCallback:(void (^_Nonnull)(MatterError * _Nonnull))commissioningCompleteCallback sessionEstablishmentStartedCallback:(void (^_Nullable)(void))sessionEstablishmentStartedCallback sessionEstablishedCallback:(void (^_Nullable)(void))sessionEstablishedCallback sessionEstablishmentErrorCallback:(void (^_Nullable)(MatterError * _Nonnull))sessionEstablishmentErrorCallback @@ -34,12 +36,14 @@ /** * This is called when request to open the commissioning window has been made. */ -@property void (^_Nullable commissioningWindowRequestedHandler)(bool); +@property void (^_Nullable commissioningWindowRequestedHandler)(MatterError * _Nonnull); + +@property void (^_Nullable commissioningWindowOpenedCallback)(MatterError * _Nonnull); /** * This is called when the commissioning has been completed */ -@property void (^_Nullable commissioningCompleteCallback)(bool); +@property void (^_Nullable commissioningCompleteCallback)(MatterError * _Nonnull); /** * This is called when the PBKDFParamRequest is received and indicates the start of the session establishment process diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.m similarity index 85% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.m index be79d40793c4c2..c05661fab54e75 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissioningCallbackHandlers.m +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/CommissioningCallbackHandlers.m @@ -20,8 +20,9 @@ @implementation CommissioningCallbackHandlers - (CommissioningCallbackHandlers * _Nonnull) - initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(bool))commissioningWindowRequestedHandler - commissioningCompleteCallback:(void (^_Nonnull)(bool))commissioningCompleteCallback + initWithCommissioningWindowRequestedHandler:(void (^_Nonnull)(MatterError * _Nonnull))commissioningWindowRequestedHandler + commissioningWindowOpenedCallback:(void (^_Nonnull)(MatterError * _Nonnull))commissioningWindowOpenedCallback + commissioningCompleteCallback:(void (^_Nonnull)(MatterError * _Nonnull))commissioningCompleteCallback sessionEstablishmentStartedCallback:(void (^_Nullable)(void))sessionEstablishmentStartedCallback sessionEstablishedCallback:(void (^_Nullable)(void))sessionEstablishedCallback sessionEstablishmentErrorCallback:(void (^_Nullable)(MatterError * _Nonnull))sessionEstablishmentErrorCallback @@ -30,6 +31,7 @@ @implementation CommissioningCallbackHandlers self = [super init]; if (self) { _commissioningWindowRequestedHandler = commissioningWindowRequestedHandler; + _commissioningWindowOpenedCallback = commissioningWindowOpenedCallback; _commissioningCompleteCallback = commissioningCompleteCallback; _sessionEstablishmentStartedCallback = sessionEstablishmentStartedCallback; _sessionEstablishedCallback = sessionEstablishedCallback; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.h similarity index 87% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.h index b9a7384b0a3f7e..d31530e0274da0 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.h @@ -17,9 +17,12 @@ #import +#import "../MCEndpoint.h" + #ifndef ContentApp_h #define ContentApp_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface ContentApp : NSObject @property uint16_t endpointId; @@ -33,6 +36,8 @@ - (instancetype)initWithEndpointId:(uint16_t)endpointId clusterIds:(NSMutableArray *)clusterIds; +- (instancetype)initWithEndpoint:(MCEndpoint *)endpoint; + - (BOOL)supportsClusterWithId:(uint32_t)clusterId; - (BOOL)supportsApplicationLauncher; diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.mm similarity index 87% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.mm index ac4649867bdb2a..fe0e92a1fab98a 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentApp.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentApp.mm @@ -17,6 +17,7 @@ #import +#import "../MCEndpoint_Internal.h" #import "ContentApp.h" #include @@ -41,6 +42,16 @@ - (instancetype)initWithEndpointId:(uint16_t)endpointId clusterIds:(NSMutableArr return self; } +- (instancetype)initWithEndpoint:(MCEndpoint *)endpoint +{ + if (self = [super init]) { + _endpointId = [endpoint.identifier unsignedShortValue]; + _clusterIds = [endpoint getServerList]; + _isInitialized = true; + } + return self; +} + - (BOOL)supportsClusterWithId:(uint32_t)clusterId { if (_clusterIds != nil) { diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentLauncherTypes.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentLauncherTypes.h similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentLauncherTypes.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentLauncherTypes.h diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentLauncherTypes.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentLauncherTypes.mm similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ContentLauncherTypes.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/ContentLauncherTypes.mm diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.h similarity index 54% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.h index a1ca48f8b87616..560e777bab814f 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCObserver.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020-2024 Project CHIP Authors + * Copyright (c) 2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,15 +15,22 @@ * limitations under the License. */ +#import "MCDataSource.h" + +#import "AppParameters.h" + #import -#ifndef MCObserver_h -#define MCObserver_h +#ifndef DataSourceCompat_h +#define DataSourceCompat_h -@protocol MCObserver +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) +@interface DataSourceCompat : NSObject -- (void)attribute:(NSObject * _Nonnull)sender valueDidChange:(NSValue * _Nullable)value oldValue:(NSValue * _Nullable)oldValue; +- (instancetype)initWithClientQueue:(dispatch_queue_t)clientQueue; +- (void)setAppParameters:(AppParameters *)appParameters; +- (void)setDacHolder:(DeviceAttestationCredentialsHolder *)dacHolder; @end -#endif /* MCObserver_h */ +#endif /* DataSourceCompat_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.mm new file mode 100644 index 00000000000000..6f23d13c0c62e9 --- /dev/null +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DataSourceCompat.mm @@ -0,0 +1,124 @@ +/** + * + * Copyright (c) 2020-2024 Project CHIP Authors + * + * 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. + */ + +#import "DataSourceCompat.h" + +#import "MCCastingApp.h" +#import "MCCommissionableData.h" +#import "MCCryptoUtils.h" +#import "MCDeviceAttestationCredentials.h" +#import "MCErrorUtils.h" + +#include +#include +#include +#include +#include +#include + +@interface DataSourceCompat () + +@property (nonatomic, strong) dispatch_queue_t clientQueue; +@property (nonatomic, strong) AppParameters * appParameters; +@property (nonatomic, strong) DeviceAttestationCredentialsHolder * dacHolder; + +@end + +@implementation DataSourceCompat + +- (instancetype)initWithClientQueue:(dispatch_queue_t)clientQueue +{ + self = [super init]; + if (self) { + _clientQueue = clientQueue; + } + return self; +} + +- (dispatch_queue_t _Nonnull)clientQueue +{ + return _clientQueue; +} + +- (void)setAppParameters:(AppParameters *)appParameters +{ + _appParameters = appParameters; +} + +- (void)setDacHolder:(DeviceAttestationCredentialsHolder *)dacHolder +{ + _dacHolder = dacHolder; +} + +- (NSData *)castingAppDidReceiveRequestForRotatingDeviceIdUniqueId:(id)sender +{ + ChipLogProgress(AppServer, "DataSourceCompat::castingAppDidReceiveRequestForRotatingDeviceIdUniqueId called"); + if (self.appParameters != nil) { + return self.appParameters.rotatingDeviceIdUniqueId; + } + return nil; +} + +- (MCCommissionableData *)castingAppDidReceiveRequestForCommissionableData:(id)sender +{ + ChipLogProgress(AppServer, "DataSourceCompat::castingAppDidReceiveRequestForCommissionableData called"); + if (self.appParameters != nil) { + return [[MCCommissionableData alloc] initWithPasscode:self.appParameters.onboardingPayload.setupPasscode discriminator:self.appParameters.onboardingPayload.setupDiscriminator spake2pIterationCount:self.appParameters.spake2pIterationCount spake2pVerifier:self.appParameters.spake2pVerifierBase64 spake2pSalt:self.appParameters.spake2pSaltBase64]; + } + return nil; +} + +- (MCDeviceAttestationCredentials *)castingAppDidReceiveRequestForDeviceAttestationCredentials:(id)sender +{ + ChipLogProgress(AppServer, "DataSourceCompat::castingAppDidReceiveRequestForDeviceAttestationCredentials called"); + if (self.dacHolder != nil) { + return [[MCDeviceAttestationCredentials alloc] initWithCertificationDeclaration:[self.dacHolder getCertificationDeclaration] firmwareInformation:[self.dacHolder getFirmwareInformation] deviceAttestationCert:[self.dacHolder getDeviceAttestationCert] productAttestationIntermediateCert:[self.dacHolder getProductAttestationIntermediateCert]]; + } + return nil; +} + +- (MatterError *)castingApp:(id)sender didReceiveRequestToSignCertificateRequest:(NSData *)csrData outRawSignature:(NSData * _Nonnull * _Nonnull)outRawSignature +{ + ChipLogProgress(AppServer, "DataSourceCompat::castingApp didReceiveRequestToSignCertificateRequest called"); + if (self.dacHolder != nil) { + // Get the private SecKey from dacHolder + SecKeyRef privateSecKey = [self.dacHolder getDeviceAttestationCertPrivateKeyRef]; + if (privateSecKey == nil) { + ChipLogError(AppServer, "DataSourceCompat::castingApp didReceiveRequestToSignCertificateRequest No privateSecKey found"); + return [MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INVALID_ARGUMENT]; + } + + // Sign csrData to get asn1SignatureData + CFErrorRef error = nil; + CFDataRef asn1SignatureData = SecKeyCreateSignature(privateSecKey, kSecKeyAlgorithmECDSASignatureMessageX962SHA256, (__bridge CFDataRef) csrData, &error); + if (error != nil) { + ChipLogError(AppServer, "DataSourceCompat::castingApp didReceiveRequestToSignCertificateRequest failed to sign message, err: %@", error); + return [MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INVALID_ARGUMENT]; + } + if (asn1SignatureData == nil) { + ChipLogError(AppServer, "DataSourceCompat::castingApp didReceiveRequestToSignCertificateRequest failed to sign message, asn1SignatureData is nil"); + return [MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INVALID_ARGUMENT]; + } + + // Convert ASN.1 DER signature to SEC1 raw format + return [MCCryptoUtils ecdsaAsn1SignatureToRawWithFeLengthBytes:32 asn1Signature:asn1SignatureData + outRawSignature:outRawSignature]; + } + + return [MCErrorUtils MatterErrorFromChipError:CHIP_ERROR_INCORRECT_STATE]; +} +@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsHolder.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DeviceAttestationCredentialsHolder.h similarity index 94% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsHolder.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DeviceAttestationCredentialsHolder.h index 44d4dee2169c43..8140d2abeaed42 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsHolder.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DeviceAttestationCredentialsHolder.h @@ -21,6 +21,7 @@ #ifndef DeviceAttestationCredentialsHolder_h #define DeviceAttestationCredentialsHolder_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface DeviceAttestationCredentialsHolder : NSObject - (DeviceAttestationCredentialsHolder * _Nonnull) diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsHolder.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DeviceAttestationCredentialsHolder.m similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DeviceAttestationCredentialsHolder.m rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DeviceAttestationCredentialsHolder.m diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.h similarity index 86% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.h index f4cf95f4be7e6a..93687bbfa0d703 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.h @@ -17,11 +17,13 @@ #import +#import "../MCCastingPlayer.h" #import "VideoPlayer.h" #ifndef DiscoveredNodeData_h #define DiscoveredNodeData_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface DiscoveredNodeData : NSObject @property NSString * deviceName; @@ -56,12 +58,16 @@ - (DiscoveredNodeData *)initWithDeviceName:(NSString *)deviceName vendorId:(uint16_t)vendorId productId:(uint16_t)productId; +- (instancetype)initWithCastingPlayer:(MCCastingPlayer *)castingPlayer; + - (bool)isPreCommissioned; - (VideoPlayer *)getConnectableVideoPlayer; - (void)setConnectableVideoPlayer:(VideoPlayer *)videoPlayer; +- (MCCastingPlayer *)getCastingPlayer; + @end #endif /* DiscoveredNodeData_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.mm similarity index 62% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.mm index f8c85e52269dbb..3d9a4b19498dab 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/DiscoveredNodeData.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/DiscoveredNodeData.mm @@ -18,12 +18,16 @@ #import #import "DiscoveredNodeData.h" +#import "VideoPlayer.h" + #include @interface DiscoveredNodeData () @property (nonatomic) VideoPlayer * connectableVideoPlayer; +@property (nonatomic) MCCastingPlayer * castingPlayer; + @end @implementation DiscoveredNodeData @@ -39,14 +43,27 @@ - (DiscoveredNodeData *)initWithDeviceName:(NSString *)deviceName vendorId:(uint return self; } -- (NSString *)description +- (instancetype)initWithCastingPlayer:(MCCastingPlayer *)castingPlayer { - if ([self isPreCommissioned]) { - return [NSString - stringWithFormat:@"%@ with Product ID: %d and Vendor ID: %d [Pre-Commissioned]", _deviceName, _productId, _vendorId]; - } else { - return [NSString stringWithFormat:@"%@ with Product ID: %d and Vendor ID: %d", _deviceName, _productId, _vendorId]; + self = [super init]; + if (self) { + _castingPlayer = castingPlayer; + _deviceType = castingPlayer.deviceType; + _vendorId = castingPlayer.vendorId; + _productId = castingPlayer.productId; + _deviceName = castingPlayer.deviceName; + _instanceName = castingPlayer.instanceName; + _hostName = castingPlayer.hostName; + _numIPs = castingPlayer.ipAddresses.count; + _ipAddresses = [castingPlayer.ipAddresses mutableCopy]; + _connectableVideoPlayer = [[VideoPlayer alloc] initWithCastingPlayer:castingPlayer]; } + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ with Product ID: %d and Vendor ID: %d", _deviceName, _productId, _vendorId]; } - (BOOL)isEqualToDiscoveredNodeData:(DiscoveredNodeData *)other @@ -88,7 +105,10 @@ - (void)setConnectableVideoPlayer:(VideoPlayer * _Nonnull)videoPlayer - (bool)isPreCommissioned { - return _connectableVideoPlayer != nil; + // Returning false will make the compat shim call the openBasicCommissioningWindow API every time. + // The shim will internally handle selecting the commissioning path or simply re-establish + // CASE (if the player nodeId/fabricIndex were found in the cache) + return false; } - (VideoPlayer *)getConnectableVideoPlayer @@ -96,4 +116,9 @@ - (VideoPlayer *)getConnectableVideoPlayer return _connectableVideoPlayer; } +- (MCCastingPlayer *)getCastingPlayer +{ + return _castingPlayer; +} + @end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MediaPlaybackTypes.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/MediaPlaybackTypes.h similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MediaPlaybackTypes.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/MediaPlaybackTypes.h diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MediaPlaybackTypes.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/MediaPlaybackTypes.mm similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MediaPlaybackTypes.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/MediaPlaybackTypes.mm diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/OnboardingPayload.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/OnboardingPayload.h similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/OnboardingPayload.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/OnboardingPayload.h diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/OnboardingPayload.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/OnboardingPayload.m similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/OnboardingPayload.m rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/OnboardingPayload.m diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/TargetNavigatorTypes.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/TargetNavigatorTypes.h similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/TargetNavigatorTypes.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/TargetNavigatorTypes.h diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/TargetNavigatorTypes.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/TargetNavigatorTypes.mm similarity index 100% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/TargetNavigatorTypes.mm rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/TargetNavigatorTypes.mm diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.h similarity index 89% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.h index 1496ff9b180d1c..fe543809dafd7b 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.h @@ -15,9 +15,12 @@ * limitations under the License. */ +#import "../MCCastingPlayer.h" + #ifndef VideoPlayer_h #define VideoPlayer_h +__attribute__((deprecated("Use the APIs described in /examples/tv-casting-app/APIs.md instead."))) @interface VideoPlayer : NSObject @property uint64_t nodeId; @@ -73,6 +76,10 @@ MACAddress:(NSString *)MACAddress lastDiscoveredMs:(uint64_t)lastDiscoveredMs; +- (instancetype)initWithCastingPlayer:(MCCastingPlayer *)castingPlayer; + +- (MCCastingPlayer *)getCastingPlayer; + @end #endif /* VideoPlayer_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.m b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.m similarity index 70% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.m rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.m index ef3a3d23f76c65..a0470bbf14a8bf 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/VideoPlayer.m +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/compat-shim/VideoPlayer.m @@ -17,8 +17,15 @@ #import +#import "ContentApp.h" #import "VideoPlayer.h" +@interface VideoPlayer () + +@property (nonatomic) MCCastingPlayer * castingPlayer; + +@end + @implementation VideoPlayer - (instancetype)init @@ -63,8 +70,33 @@ - (instancetype)initWithNodeId:(uint64_t)nodeId return self; } +- (instancetype)initWithCastingPlayer:(MCCastingPlayer *)castingPlayer +{ + if (self = [super init]) { + _castingPlayer = castingPlayer; + _deviceName = castingPlayer.deviceName; + _vendorId = castingPlayer.vendorId; + _productId = castingPlayer.productId; + _deviceType = castingPlayer.deviceType; + _hostName = castingPlayer.hostName; + _instanceName = castingPlayer.instanceName; + _contentApps = [NSMutableArray new]; + NSArray * endpoints = castingPlayer.endpoints; + for (MCEndpoint * endpoint in endpoints) { + [_contentApps addObject:[[ContentApp alloc] initWithEndpoint:endpoint]]; + } + _isInitialized = true; + } + return self; +} + - (NSString *)description { return [NSString stringWithFormat:@"%@ with Product ID: %d, Vendor ID: %d", _deviceName, _productId, _vendorId]; } + +- (MCCastingPlayer *)getCastingPlayer +{ + return _castingPlayer; +} @end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCEndpointClusterType.h similarity index 82% rename from examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h rename to examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCEndpointClusterType.h index 7137dd1ed96042..d60f980f66a1c7 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpointClusterType.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/MCEndpointClusterType.h @@ -21,8 +21,12 @@ typedef enum _MCEndpointClusterType { MCEndpointClusterTypeApplicationBasic, + MCEndpointClusterTypeApplicationLauncher, MCEndpointClusterTypeContentLauncher, - MCEndpointClusterTypeMediaPlayback + MCEndpointClusterTypeKeypadInput, + MCEndpointClusterTypeMediaPlayback, + MCEndpointClusterTypeOnOff, + MCEndpointClusterTypeTargetNavigator } MCEndpointClusterType; #endif /* MCEndpointClusterType_h */ diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj index e48185f4c9d64c..2d4a142cd515a5 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting.xcodeproj/project.pbxproj @@ -15,10 +15,6 @@ 3C621CB32B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CB22B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift */; }; 3C621CB52B607FFD005CDBA3 /* MCActionSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C621CB42B607FFD005CDBA3 /* MCActionSelectorView.swift */; }; 3C69204A2AA1368F00D0F613 /* MCInitializationExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C6920492AA1368F00D0F613 /* MCInitializationExample.swift */; }; - 3C81C75328F8C79E001CB9D1 /* StartFromCacheView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75228F8C79E001CB9D1 /* StartFromCacheView.swift */; }; - 3C81C75528F8C7B6001CB9D1 /* StartFromCacheViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75428F8C7B6001CB9D1 /* StartFromCacheViewModel.swift */; }; - 3C81C75728F8E418001CB9D1 /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75628F8E418001CB9D1 /* ConnectionView.swift */; }; - 3C81C75928F8E42D001CB9D1 /* ConnectionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C81C75828F8E42D001CB9D1 /* ConnectionViewModel.swift */; }; 3C94377D2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C94377C2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift */; }; 3C94377F2B364D510096E5F4 /* MCConnectionExampleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C94377E2B364D510096E5F4 /* MCConnectionExampleViewModel.swift */; }; 3C94378E2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C94378D2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift */; }; @@ -71,10 +67,6 @@ 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissioningView.swift; sourceTree = ""; }; 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissionerDiscoveryViewModel.swift; sourceTree = ""; }; 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommissioningViewModel.swift; sourceTree = ""; }; - 3C81C75228F8C79E001CB9D1 /* StartFromCacheView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartFromCacheView.swift; sourceTree = ""; }; - 3C81C75428F8C7B6001CB9D1 /* StartFromCacheViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartFromCacheViewModel.swift; sourceTree = ""; }; - 3C81C75628F8E418001CB9D1 /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = ""; }; - 3C81C75828F8E42D001CB9D1 /* ConnectionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionViewModel.swift; sourceTree = ""; }; 3C94377C2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCDiscoveryExampleViewModel.swift; sourceTree = ""; }; 3C94377E2B364D510096E5F4 /* MCConnectionExampleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCConnectionExampleViewModel.swift; sourceTree = ""; }; 3C94378D2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCDiscoveryExampleView.swift; sourceTree = ""; }; @@ -108,6 +100,25 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3C996C2C2BD9C2B40027BD8A /* compat */ = { + isa = PBXGroup; + children = ( + 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */, + 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */, + 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */, + 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */, + 3CA1CA7928E281080023ED44 /* ClusterSelectorView.swift */, + 3CA19434285BA780004768D5 /* ContentLauncherView.swift */, + 3CA19436285BA877004768D5 /* ContentLauncherViewModel.swift */, + 3CA1CA7B28E282150023ED44 /* MediaPlaybackView.swift */, + 3CA1CA7D28E284950023ED44 /* MediaPlaybackViewModel.swift */, + EAF14298296D561900E17793 /* CertTestView.swift */, + EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */, + 3CAC955A29BA948700BEA5C3 /* ExampleDAC.swift */, + ); + path = compat; + sourceTree = ""; + }; 3C9ACC02284ABBD600718B2D /* Frameworks */ = { isa = PBXGroup; children = ( @@ -137,9 +148,11 @@ 3CC0E8F82841DD3400EC6A18 /* TvCasting */ = { isa = PBXGroup; children = ( + 3C996C2C2BD9C2B40027BD8A /* compat */, 3CC0E8FD2841DD3500EC6A18 /* Assets.xcassets */, 3C75075E284C1DF800D7DB3A /* TvCasting.entitlements */, 3CC0E8F92841DD3400EC6A18 /* TvCastingApp.swift */, + 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */, 3C6920492AA1368F00D0F613 /* MCInitializationExample.swift */, 3C94378D2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift */, 3C94377C2B364D380096E5F4 /* MCDiscoveryExampleViewModel.swift */, @@ -152,23 +165,6 @@ 3C621CB22B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift */, 3C40586D2B632DC500C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleView.swift */, 3C40586F2B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift */, - EAF14298296D561900E17793 /* CertTestView.swift */, - EAF1429A296D57DF00E17793 /* CertTestViewModel.swift */, - 3CC0E8FB2841DD3400EC6A18 /* ContentView.swift */, - 3C81C75228F8C79E001CB9D1 /* StartFromCacheView.swift */, - 3C81C75428F8C7B6001CB9D1 /* StartFromCacheViewModel.swift */, - 3C81C75628F8E418001CB9D1 /* ConnectionView.swift */, - 3C81C75828F8E42D001CB9D1 /* ConnectionViewModel.swift */, - 3C7507AC285299DF00D7DB3A /* CommissionerDiscoveryView.swift */, - 3C7507B62853A3AD00D7DB3A /* CommissionerDiscoveryViewModel.swift */, - 3C7507AE28529A5F00D7DB3A /* CommissioningView.swift */, - 3C7507B82853EFF000D7DB3A /* CommissioningViewModel.swift */, - 3CAC955A29BA948700BEA5C3 /* ExampleDAC.swift */, - 3CA1CA7928E281080023ED44 /* ClusterSelectorView.swift */, - 3CA19434285BA780004768D5 /* ContentLauncherView.swift */, - 3CA19436285BA877004768D5 /* ContentLauncherViewModel.swift */, - 3CA1CA7B28E282150023ED44 /* MediaPlaybackView.swift */, - 3CA1CA7D28E284950023ED44 /* MediaPlaybackViewModel.swift */, 3CC0E8FF2841DD3500EC6A18 /* Preview Content */, ); path = TvCasting; @@ -267,17 +263,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3C81C75328F8C79E001CB9D1 /* StartFromCacheView.swift in Sources */, 3C94377F2B364D510096E5F4 /* MCConnectionExampleViewModel.swift in Sources */, 3C4058702B632DDB00C7C6D6 /* MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift in Sources */, - 3C81C75528F8C7B6001CB9D1 /* StartFromCacheViewModel.swift in Sources */, 3CCB8745286A5D0F00771BAD /* CommissionerDiscoveryView.swift in Sources */, 3C621CB12B6078A9005CDBA3 /* MCApplicationBasicReadVendorIDExampleView.swift in Sources */, 3CCB8746286A5D0F00771BAD /* CommissionerDiscoveryViewModel.swift in Sources */, 3C4F52302B51F32000BB8A10 /* MCContentLauncherLaunchURLExampleViewModel.swift in Sources */, 3C621CB32B6078B7005CDBA3 /* MCApplicationBasicReadVendorIDExampleViewModel.swift in Sources */, 3C621CB52B607FFD005CDBA3 /* MCActionSelectorView.swift in Sources */, - 3C81C75928F8E42D001CB9D1 /* ConnectionViewModel.swift in Sources */, 3CA1CA7A28E281080023ED44 /* ClusterSelectorView.swift in Sources */, 3C94378E2B3B3CB00096E5F4 /* MCDiscoveryExampleView.swift in Sources */, EAF14299296D561900E17793 /* CertTestView.swift in Sources */, @@ -291,7 +284,6 @@ 3CCB8749286A5D0F00771BAD /* ContentLauncherView.swift in Sources */, 3CCB874A286A5D0F00771BAD /* ContentLauncherViewModel.swift in Sources */, EAF1429B296D57DF00E17793 /* CertTestViewModel.swift in Sources */, - 3C81C75728F8E418001CB9D1 /* ConnectionView.swift in Sources */, 3CC0E8FC2841DD3400EC6A18 /* ContentView.swift in Sources */, 3CA1CA7C28E282150023ED44 /* MediaPlaybackView.swift in Sources */, 3CC0E8FA2841DD3400EC6A18 /* TvCastingApp.swift in Sources */, diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift deleted file mode 100644 index ec0c542d942e38..00000000000000 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningViewModel.swift +++ /dev/null @@ -1,118 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - - -import Foundation -import os.log - -class CommissioningViewModel: ObservableObject { - let Log = Logger(subsystem: "com.matter.casting", - category: "CommissioningViewModel") - - @Published var udcRequestSent: Bool?; - - @Published var commisisoningWindowOpened: Bool?; - - @Published var commisisoningComplete: Bool?; - - @Published var connectionSuccess: Bool?; - - @Published var connectionStatus: String?; - - func prepareForCommissioning(selectedCommissioner: DiscoveredNodeData?) { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.setDacHolder(ExampleDAC(), clientQueue: DispatchQueue.main, setDacHolderStatus: { (error: MatterError) -> () in - DispatchQueue.main.async { - self.Log.info("CommissioningViewModel.setDacHolder status was \(error)") - if(error.code == 0) - { - self.openBasicCommissioningWindow() - } - } - }) - } - - // Send User directed commissioning request if a commissioner with a known IP addr was selected - if(selectedCommissioner != nil && selectedCommissioner!.numIPs > 0) - { - sendUserDirectedCommissioningRequest(selectedCommissioner: selectedCommissioner) - } - } - - private func openBasicCommissioningWindow() { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.openBasicCommissioningWindow(DispatchQueue.main, - commissioningCallbackHandlers: CommissioningCallbackHandlers( - commissioningWindowRequestedHandler: { (result: Bool) -> () in - DispatchQueue.main.async { - self.Log.info("Commissioning Window opening status: \(result)") - self.commisisoningWindowOpened = result - } - }, - commissioningCompleteCallback: { (result: Bool) -> () in - self.Log.info("Commissioning status: \(result)") - DispatchQueue.main.async { - self.commisisoningComplete = result - } - }, - sessionEstablishmentStartedCallback: { - self.Log.info("PASE session establishment started") - }, - sessionEstablishedCallback: { - self.Log.info("PASE session established") - }, - sessionEstablishmentErrorCallback: { (err: MatterError) -> () in - self.Log.info("PASE session establishment error : \(err)") - }, - sessionEstablishmentStoppedCallback: { - self.Log.info("PASE session establishment stopped") - } - ), - onConnectionSuccessCallback: { (videoPlayer: VideoPlayer) -> () in - DispatchQueue.main.async { - self.connectionSuccess = true - self.connectionStatus = "Connected to \(String(describing: videoPlayer))" - self.Log.info("CommissioningViewModel.verifyOrEstablishConnection.onConnectionSuccessCallback called with \(videoPlayer.nodeId)") - } - }, - onConnectionFailureCallback: { (error: MatterError) -> () in - DispatchQueue.main.async { - self.connectionSuccess = false - self.connectionStatus = "Failed to connect to video player!" - self.Log.info("CommissioningViewModel.verifyOrEstablishConnection.onConnectionFailureCallback called with \(error)") - } - }, - onNewOrUpdatedEndpointCallback: { (contentApp: ContentApp) -> () in - DispatchQueue.main.async { - self.Log.info("CommissioningViewModel.openBasicCommissioningWindow.onNewOrUpdatedEndpointCallback called with \(contentApp.endpointId)") - } - }) - } - - } - - private func sendUserDirectedCommissioningRequest(selectedCommissioner: DiscoveredNodeData?) { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.sendUserDirectedCommissioningRequest(selectedCommissioner!, clientQueue: DispatchQueue.main, udcRequestSentHandler: { (result: Bool) -> () in - self.udcRequestSent = result - }) - } - } -} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionView.swift deleted file mode 100644 index c7bfacc6cca49e..00000000000000 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionView.swift +++ /dev/null @@ -1,78 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - - -import SwiftUI - -struct ConnectionView: View { - var selectedVideoPlayer: VideoPlayer? - - @StateObject var viewModel = ConnectionViewModel(); - - init(_selectedVideoPlayer: VideoPlayer?) { - self.selectedVideoPlayer = _selectedVideoPlayer - } - - var body: some View { - VStack(alignment: .leading) { - if let requestSent = viewModel.requestSent { - if(requestSent) - { - Text("Sent request to verify or connect to video player").padding() - } - else - { - Text("Failed in sending request to verify or connect to video player!").foregroundColor(Color.red).padding() - } - - if let connectionSuccess = viewModel.connectionSuccess - { - if let connectionStatus = viewModel.connectionStatus - { - Text(connectionStatus).padding() - } - - if(connectionSuccess) - { - NavigationLink( - destination: ClusterSelectorView(), - label: { - Text("Next") - .frame(width: 100, height: 30, alignment: .center) - .border(Color.black, width: 1) - } - ).background(Color.blue) - .foregroundColor(Color.white) - .frame(maxHeight: .infinity, alignment: .bottom) - .padding() - } - } - } - } - .navigationTitle("Connecting...") - .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) - .onAppear(perform: { - viewModel.verifyOrEstablishConnection(selectedVideoPlayer: self.selectedVideoPlayer) - }) - } -} - -struct ConnectionView_Previews: PreviewProvider { - static var previews: some View { - ConnectionView(_selectedVideoPlayer: nil) - } -} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionViewModel.swift deleted file mode 100644 index 2d97a47ab3966c..00000000000000 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ConnectionViewModel.swift +++ /dev/null @@ -1,63 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - - -import Foundation -import os.log - -class ConnectionViewModel: ObservableObject { - let Log = Logger(subsystem: "com.matter.casting", - category: "ConnectionViewModel") - - @Published var requestSent: Bool?; - - @Published var connectionSuccess: Bool?; - - @Published var connectionStatus: String?; - - func verifyOrEstablishConnection(selectedVideoPlayer: VideoPlayer?) { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.verifyOrEstablishConnection(selectedVideoPlayer!, clientQueue: DispatchQueue.main, - requestSentHandler: { (error: MatterError) -> () in - DispatchQueue.main.async { - self.requestSent = (error.code == 0) - self.Log.info("ConnectionViewModel.verifyOrEstablishConnection.requestSentHandler called with \(error)") - } - }, - onConnectionSuccessCallback: { (videoPlayer: VideoPlayer) -> () in - DispatchQueue.main.async { - self.connectionSuccess = true - self.connectionStatus = "Connected to \(String(describing: videoPlayer))" - self.Log.info("ConnectionViewModel.verifyOrEstablishConnection.onConnectionSuccessCallback called with \(videoPlayer.nodeId)") - } - }, - onConnectionFailureCallback: { (error: MatterError) -> () in - DispatchQueue.main.async { - self.connectionSuccess = false - self.connectionStatus = "Failed to connect to video player!" - self.Log.info("ConnectionViewModel.verifyOrEstablishConnection.onConnectionFailureCallback called with \(error)") - } - }, - onNewOrUpdatedEndpointCallback: { (contentApp: ContentApp) -> () in - DispatchQueue.main.async { - self.Log.info("ConnectionViewModel.verifyOrEstablishConnection.onNewOrUpdatedEndpointCallback called with \(contentApp.endpointId)") - } - }) - } - } -} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift index 701fada1fe62d9..afc1207e63dd00 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentView.swift @@ -26,7 +26,7 @@ struct ContentView: View { } else { - StartFromCacheView() + CommissionerDiscoveryView() } } } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift index 5d30f096052a84..e7d3581dd07350 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift @@ -61,8 +61,7 @@ class MCMediaPlaybackSubscribeToCurrentStateExampleViewModel: ObservableObject { // call read on currentStateAttribute and pass in a completion block - currentStateAttribute!.read(nil) { context, before, after, err in - + currentStateAttribute!.subscribe(nil, completion: { context, before, after, err in let dateFormatter = DateFormatter() dateFormatter.dateFormat = "HH:mm:ss" let currentTime = dateFormatter.string(from: Date()) @@ -85,7 +84,7 @@ class MCMediaPlaybackSubscribeToCurrentStateExampleViewModel: ObservableObject { self.status = "Read CurrentState value: \(String(describing: after)) at \(currentTime)" } } - } + }, minInterval: 0, maxInterval: 1) } else { diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheView.swift deleted file mode 100644 index 0d2bad3e29ba1f..00000000000000 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheView.swift +++ /dev/null @@ -1,83 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - -import SwiftUI - -extension VideoPlayer : Identifiable { - public var id: String { - deviceName - } -} - -struct StartFromCacheView: View { - @StateObject var viewModel = StartFromCacheViewModel() - - var body: some View { - VStack(alignment: .leading) { - Button("Purge cache", action: { - viewModel.purgeAndReReadCache() - }) - .frame(width: 200, height: 30, alignment: .center) - .border(Color.black, width: 1) - .background(Color.blue) - .foregroundColor(Color.white) - .padding() - - NavigationLink( - destination: CommissionerDiscoveryView(), - label: { - Text("Skip to commissioner discovery >>") - .frame(width: 300, height: 30, alignment: .center) - .border(Color.black, width: 1) - } - ).background(Color.blue) - .foregroundColor(Color.white) - .padding() - - if(viewModel.videoPlayers.isEmpty) - { - Text("No cached video players.") - } - else - { - Text("Pick a Video player") - ForEach(viewModel.videoPlayers) { videoPlayer in - NavigationLink( - destination: ConnectionView(_selectedVideoPlayer: videoPlayer), - label: { - Text(videoPlayer.description) - } - ) - .frame(width: 350, height: 50, alignment: .center) - .border(Color.black, width: 1) - .background(Color.blue) - .foregroundColor(Color.white) - .padding(1) - } - } - } - .navigationTitle("Starting from Cache") - .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top) - .onAppear(perform: {viewModel.readFromCache()}) - } -} - -struct StartFromCacheView_Previews: PreviewProvider { - static var previews: some View { - StartFromCacheView() - } -} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheViewModel.swift deleted file mode 100644 index 3b12b5fa3c867f..00000000000000 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/StartFromCacheViewModel.swift +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - -import Foundation -import os.log - -class StartFromCacheViewModel: ObservableObject { - let Log = Logger(subsystem: "com.matter.casting", - category: "StartFromCacheViewModel") - - @Published var videoPlayers: [VideoPlayer] = [] - - func readFromCache() { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.readCachedVideoPlayers(DispatchQueue.main, readCachedVideoPlayersHandler: { (cachedVideoPlayers: NSMutableArray?) -> () in - if(cachedVideoPlayers != nil) - { - self.videoPlayers = cachedVideoPlayers! as! [VideoPlayer] - } - }) - } - } - - func purgeAndReReadCache() { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - castingServerBridge.purgeCache(DispatchQueue.main, responseHandler: { (error: MatterError) -> () in - DispatchQueue.main.async { - self.Log.info("purgeCache returned \(error)") - self.readFromCache() - } - }) - } - } -} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/TvCastingApp.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/TvCastingApp.swift index d6949900f43202..ce31f4f79446ce 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/TvCastingApp.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/TvCastingApp.swift @@ -61,7 +61,7 @@ struct TvCastingApp: App { appParameters.onboardingPayload = onboardingParameters - let err = castingServerBridge.initializeApp(appParameters, clientQueue: DispatchQueue.main, initAppStatusHandler: { (result: Bool) -> () in + let err = castingServerBridge.initializeApp(appParameters, clientQueue: DispatchQueue.main, initAppStatusHandler: { (result: MatterError) -> () in self.Log.info("initializeApp result \(result)") }) self.Log.info("initializeApp return value \(err)") diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CertTestView.swift similarity index 100% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CertTestView.swift diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CertTestViewModel.swift similarity index 98% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CertTestViewModel.swift index 7975f80604ac50..cb7f6b2f7bc489 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CertTestViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CertTestViewModel.swift @@ -28,20 +28,20 @@ private class CallbackHelper { self.certTestViewModel = certTestViewModel } - func responseCallback(succeeded: Bool) + func responseCallback(err: MatterError) { - logger.info("CertTestViewModel.responseCallback.\(self.testCaseName) succeeded? \(succeeded)") - if (succeeded) { + logger.info("CertTestViewModel.responseCallback.\(self.testCaseName) err? \(err)") + if (err == MATTER_NO_ERROR) { certTestViewModel.onTestPassed(testCaseName) } else { certTestViewModel.onTestFailed(testCaseName) } } - func requestSentHandler(succeeded: Bool) + func requestSentHandler(err: MatterError) { - logger.info("CertTestViewModel.requestSentHandler.\(self.testCaseName) succeeded? \(succeeded)") - if (!succeeded) { + logger.info("CertTestViewModel.requestSentHandler.\(self.testCaseName) err? \(err)") + if (err != MATTER_NO_ERROR) { certTestViewModel.onTestFailed(testCaseName) } } @@ -49,7 +49,7 @@ private class CallbackHelper { func requestSentHandlerError(result: MatterError) { logger.warning("CertTestViewModel.requestSentHandler.\(self.testCaseName). Code : \(result.code). Message : \(result.message ?? "")") - requestSentHandler(succeeded: result.code == 0) + requestSentHandler(err: result) } func successCallbackString(result: String) diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ClusterSelectorView.swift similarity index 97% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ClusterSelectorView.swift index 9dbc9f16d84fa6..308f26f03fa433 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ClusterSelectorView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ClusterSelectorView.swift @@ -17,6 +17,7 @@ import SwiftUI +@available(*, deprecated, message: "Refer to MCActionSelectorView") struct ClusterSelectorView: View { var body: some View { VStack(alignment: .leading) { diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryView.swift similarity index 82% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryView.swift index 7a33fc7b19e271..84928b2aab015a 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryView.swift @@ -23,22 +23,12 @@ extension DiscoveredNodeData : Identifiable { } } +@available(*, deprecated, message: "Refer to MCDiscoveryExampleView") struct CommissionerDiscoveryView: View { @StateObject var viewModel = CommissionerDiscoveryViewModel() var body: some View { VStack(alignment: .leading) { - NavigationLink( - destination: CommissioningView(_selectedCommissioner: nil), - label: { - Text("Skip to manual commissioning >>") - .frame(width: 300, height: 30, alignment: .center) - .border(Color.black, width: 1) - } - ).background(Color.blue) - .foregroundColor(Color.white) - .padding() - Button("Discover commissioners", action: viewModel.discoverAndUpdate) .frame(width: 200, height: 30, alignment: .center) .border(Color.black, width: 1) @@ -58,7 +48,7 @@ struct CommissionerDiscoveryView: View { destination: { if(commissioner.isPreCommissioned()) { - ConnectionView(_selectedVideoPlayer: commissioner.getConnectableVideoPlayer()) + Text("Error: unexpected value for commissioner.isPreCommissioned: true") } else { diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryViewModel.swift similarity index 57% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryViewModel.swift index 3bc7492de10dac..02ee32e54a34c9 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissionerDiscoveryViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissionerDiscoveryViewModel.swift @@ -30,14 +30,14 @@ class CommissionerDiscoveryViewModel: ObservableObject { if let castingServerBridge = CastingServerBridge.getSharedInstance() { castingServerBridge.discoverCommissioners(DispatchQueue.main, - discoveryRequestSentHandler: { (result: Bool) -> () in - self.discoveryRequestStatus = result + discoveryRequestSentHandler: { (result: MatterError) -> () in + self.discoveryRequestStatus = (result == MATTER_NO_ERROR) }, discoveredCommissionerHandler: { (commissioner: DiscoveredNodeData) -> () in self.Log.info("discoveredCommissionerHandler called with \(commissioner)") if(self.commissioners.contains(commissioner)) { - var index = self.commissioners.firstIndex(of: commissioner) + let index = self.commissioners.firstIndex(of: commissioner) self.commissioners[index!] = commissioner self.Log.info("Updating previously discovered commissioner \(commissioner.description)") } @@ -52,37 +52,5 @@ class CommissionerDiscoveryViewModel: ObservableObject { } ) } - - /* Deprecated usage - Task { - try? await Task.sleep(nanoseconds: 5_000_000_000) // Wait for commissioners to respond - updateCommissioners() - }*/ - } - - private func updateCommissioners() { - if let castingServerBridge = CastingServerBridge.getSharedInstance() - { - var i: Int32 = 0 - var commissioner: DiscoveredNodeData?; - repeat { - castingServerBridge.getDiscoveredCommissioner(i, clientQueue: DispatchQueue.main, discoveredCommissionerHandler: { (result: DiscoveredNodeData?) -> () in - commissioner = result; - if(commissioner != nil){ - if(self.commissioners.contains(commissioner!)) - { - var index = self.commissioners.firstIndex(of: commissioner!) - self.commissioners[index!] = commissioner! - self.Log.info("Updating previously discovered commissioner \(commissioner!.description)") - } - else - { - self.commissioners.append(commissioner!) - } - } - }) - i += 1 - } while(commissioner != nil) - } } } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningView.swift similarity index 78% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningView.swift index 923d986ce6d6d5..fc49e3e0bff8dd 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/CommissioningView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningView.swift @@ -18,6 +18,7 @@ import SwiftUI +@available(*, deprecated, message: "Refer to MCConnectionExampleView") struct CommissioningView: View { var selectedCommissioner: DiscoveredNodeData? @@ -30,30 +31,24 @@ struct CommissioningView: View { var body: some View { VStack(alignment: .leading) { if(viewModel.commisisoningWindowOpened == true) { - Text("Commissioning window opened.").padding() + Text("Onboarding payload for Commissioning if needed:").padding() - Text("Onboarding PIN: " + String((CastingServerBridge.getSharedInstance()?.getOnboardingPayload().setupPasscode)!)) + Text("Passcode: " + String((CastingServerBridge.getSharedInstance()?.getOnboardingPayload().setupPasscode)!)) .border(Color.blue, width: 1) .padding() Text("Discriminator: " + String((CastingServerBridge.getSharedInstance()?.getOnboardingPayload().setupDiscriminator)!)) .border(Color.blue, width: 1) .padding() - if(self.selectedCommissioner != nil) + if(viewModel.udcRequestSent == true) { - if(viewModel.udcRequestSent == true) - { - Text("Complete commissioning on " + (selectedCommissioner?.deviceName)!) - .padding() - } - else if(viewModel.udcRequestSent == false) { - Text("Could not send user directed commissioning request to " + (selectedCommissioner?.deviceName)! + "! Complete commissioning manually!") - .foregroundColor(Color.red) - .padding() - } + Text("Complete commissioning on " + (selectedCommissioner?.deviceName)!) + .padding() } - else{ - Text("Complete commissioning with a commissioner manually!").padding() + else if(viewModel.udcRequestSent == false) { + Text("Could not send user directed commissioning request to " + (selectedCommissioner?.deviceName)!) + .foregroundColor(Color.red) + .padding() } } else if(viewModel.commisisoningWindowOpened == false) { diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningViewModel.swift new file mode 100644 index 00000000000000..af068b6d5ea8db --- /dev/null +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/CommissioningViewModel.swift @@ -0,0 +1,118 @@ +/** + * + * Copyright (c) 2020-2022 Project CHIP Authors + * + * 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. + */ + + +import Foundation +import os.log + +class CommissioningViewModel: ObservableObject { + let Log = Logger(subsystem: "com.matter.casting", + category: "CommissioningViewModel") + + @Published var udcRequestSent: Bool?; + + @Published var commisisoningWindowOpened: Bool?; + + @Published var commisisoningComplete: Bool?; + + @Published var connectionSuccess: Bool?; + + @Published var connectionStatus: String?; + + // content app that the tv-casting-app wants to cast to + let kTargetContentAppVendorId:UInt16 = 65521; + + func prepareForCommissioning(selectedCommissioner: DiscoveredNodeData?) { + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + castingServerBridge.setDacHolder(ExampleDAC(), clientQueue: DispatchQueue.main, setDacHolderStatus: { (error: MatterError) -> () in + DispatchQueue.main.async { + self.Log.info("CommissioningViewModel.setDacHolder status was \(error)") + if(error.code == 0) + { + castingServerBridge.openBasicCommissioningWindow(DispatchQueue.main, + commissioningCallbackHandlers: CommissioningCallbackHandlers( + commissioningWindowRequestedHandler: { (result: MatterError) -> () in + DispatchQueue.main.async { + self.Log.info("Commissioning Window Requested status: \(result)") + self.commisisoningWindowOpened = (result.code == 0) + } + }, + commissioningWindowOpenedCallback: { (result: MatterError) -> () in + self.Log.info("Commissioning Window Opened status: \(result)") + DispatchQueue.main.async { + self.commisisoningWindowOpened = (result.code == 0) + // Send User directed commissioning request if a commissioner with a known IP addr was selected + if(selectedCommissioner != nil && selectedCommissioner!.numIPs > 0) + { + self.sendUserDirectedCommissioningRequest(selectedCommissioner: selectedCommissioner) + } + } + }, + commissioningCompleteCallback: { (result: MatterError) -> () in + self.Log.info("Commissioning status: \(result)") + DispatchQueue.main.async { + self.commisisoningComplete = (result.code == 0) + } + }, + sessionEstablishmentStartedCallback: { + self.Log.info("PASE session establishment started") + }, + sessionEstablishedCallback: { + self.Log.info("PASE session established") + }, + sessionEstablishmentErrorCallback: { (err: MatterError) -> () in + self.Log.info("PASE session establishment error : \(err)") + }, + sessionEstablishmentStoppedCallback: { + self.Log.info("PASE session establishment stopped") + } + ), + onConnectionSuccessCallback: { (videoPlayer: VideoPlayer) -> () in + DispatchQueue.main.async { + self.connectionSuccess = true + self.connectionStatus = "Connected to \(String(describing: videoPlayer))" + self.Log.info("CommissioningViewModel.verifyOrEstablishConnection.onConnectionSuccessCallback called with \(videoPlayer.nodeId)") + } + }, + onConnectionFailureCallback: { (error: MatterError) -> () in + DispatchQueue.main.async { + self.connectionSuccess = false + self.connectionStatus = "Failed to connect to video player!" + self.Log.info("CommissioningViewModel.verifyOrEstablishConnection.onConnectionFailureCallback called with \(error)") + } + }, + onNewOrUpdatedEndpointCallback: { (contentApp: ContentApp) -> () in + DispatchQueue.main.async { + self.Log.info("CommissioningViewModel.openBasicCommissioningWindow.onNewOrUpdatedEndpointCallback called with \(contentApp.endpointId)") + } + }) + } + } + }) + } + } + + private func sendUserDirectedCommissioningRequest(selectedCommissioner: DiscoveredNodeData?) { + if let castingServerBridge = CastingServerBridge.getSharedInstance() + { + castingServerBridge.sendUserDirectedCommissioningRequest(selectedCommissioner!, clientQueue: DispatchQueue.main, udcRequestSentHandler: { (result: MatterError) -> () in + self.udcRequestSent = (result.code == 0) + }, desiredContentAppVendorId: kTargetContentAppVendorId) + } + } +} diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherView.swift similarity index 97% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherView.swift index dc15dc66876fa6..1852a4691f437c 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherView.swift @@ -23,6 +23,7 @@ extension ContentApp : Identifiable { } } +@available(*, deprecated, message: "Refer to MCContentLauncherLaunchURLExampleView") struct ContentLauncherView: View { @StateObject var viewModel = ContentLauncherViewModel() diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherViewModel.swift similarity index 89% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherViewModel.swift index 7003525e8d3360..3c68d1b5ab6a84 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ContentLauncherViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ContentLauncherViewModel.swift @@ -48,16 +48,16 @@ class ContentLauncherViewModel: ObservableObject { .contentLauncher_launchUrl(targetContentApp!, contentUrl: contentUrl!, contentDisplayStr: contentDisplayStr!, responseCallback: - { (result: Bool) -> () in + { (result: MatterError) -> () in self.Log.info("ContentLauncherViewModel.launchUrl.launchUrlResponseCallback result \(result)") DispatchQueue.main.async { - self.status = result ? "Launched URL successfully" : "Launch URL failure!" + self.status = (result == MATTER_NO_ERROR) ? "Launched URL successfully" : "Launch URL failure!" } }, clientQueue: DispatchQueue.main, - requestSentHandler: { (result: Bool) -> () in + requestSentHandler: { (result: MatterError) -> () in self.Log.info("ContentLauncherViewModel.launchUrl.launcUrlRequestSentHandler result \(result)") - self.status = result ? "Sent Launch URL request" : "Failed to send Launch URL request!" + self.status = (result == MATTER_NO_ERROR) ? "Sent Launch URL request" : "Failed to send Launch URL request!" }) } } diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/ExampleDAC.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ExampleDAC.swift similarity index 100% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/ExampleDAC.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/ExampleDAC.swift diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MediaPlaybackView.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/MediaPlaybackView.swift similarity index 97% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/MediaPlaybackView.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/MediaPlaybackView.swift index b41835adb0c139..8d66639cbfba53 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MediaPlaybackView.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/MediaPlaybackView.swift @@ -17,6 +17,7 @@ import SwiftUI +@available(*, deprecated, message: "Refer to MCMediaPlaybackSubscribeToCurrentStateExampleView") struct MediaPlayerView: View { @StateObject var viewModel = MediaPlaybackViewModel() diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MediaPlaybackViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/MediaPlaybackViewModel.swift similarity index 100% rename from examples/tv-casting-app/darwin/TvCasting/TvCasting/MediaPlaybackViewModel.swift rename to examples/tv-casting-app/darwin/TvCasting/TvCasting/compat/MediaPlaybackViewModel.swift diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index 0f455d6b4c9a44..a712c1733dc1a8 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -113,6 +113,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Forcing expiry of armed FailSafe timer"); // ChipDeviceEventHandler will handle the kFailSafeTimerExpired event by Opening the Basic Commissioning Window and Sending // the User Directed Commissioning Request + support::ChipDeviceEventHandler::SetUdcStatus(false); chip::Server::GetInstance().GetFailSafeContext().ForceFailSafeTimerExpiry(); } else diff --git a/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp b/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp index 819c0299945ed4..9793b6c5fc6316 100644 --- a/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp +++ b/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp @@ -422,14 +422,14 @@ std::vector CastingStore::ReadAll() ChipLogError(AppServer, "TLVReader.ExitContainer failed %" CHIP_ERROR_FORMAT, err.Format())); // create a castingPlayer with Endpoints and add it to the castingPlayers to be returned - core::CastingPlayer castingPlayer(attributes); + core::CastingPlayer * castingPlayer = new core::CastingPlayer(attributes); for (auto & endpointAttributes : endpointAttributesList) { - std::shared_ptr endpoint(new core::Endpoint(&castingPlayer, endpointAttributes)); + std::shared_ptr endpoint(new core::Endpoint(castingPlayer, endpointAttributes)); endpoint->RegisterClusters(endpointServerListMap[endpointAttributes.mId]); - castingPlayer.RegisterEndpoint(endpoint); + castingPlayer->RegisterEndpoint(endpoint); } - castingPlayers.push_back(castingPlayer); + castingPlayers.push_back(*castingPlayer); continue; } } diff --git a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp index b7136b3583884f..bddc64f67fb620 100644 --- a/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp +++ b/examples/tv-casting-app/tv-casting-common/support/ChipDeviceEventHandler.cpp @@ -91,7 +91,22 @@ void ChipDeviceEventHandler::Handle(const chip::DeviceLayer::ChipDeviceEvent * e void ChipDeviceEventHandler::HandleFailSafeTimerExpired() { - ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleFailSafeTimerExpired called"); + // if UDC was in progress (when the Fail-Safe timer expired), reset TargetCastingPlayer commissioning state and return early + if (sUdcInProgress) + { + ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleFailSafeTimerExpired when sUdcInProgress: %d, returning early", + sUdcInProgress); + sUdcInProgress = false; + CastingPlayer::GetTargetCastingPlayer()->mConnectionState = CASTING_PLAYER_NOT_CONNECTED; + CastingPlayer::GetTargetCastingPlayer()->mOnCompleted(CHIP_ERROR_TIMEOUT, nullptr); + CastingPlayer::GetTargetCastingPlayer()->mOnCompleted = nullptr; + CastingPlayer::GetTargetCastingPlayer()->mTargetCastingPlayer = nullptr; + return; + } + + // if UDC was NOT in progress (when the Fail-Safe timer expired), start UDC + ChipLogProgress(AppServer, "ChipDeviceEventHandler::HandleFailSafeTimerExpired when sUdcInProgress: %d, starting UDC", + sUdcInProgress); chip::DeviceLayer::SystemLayer().StartTimer( chip::System::Clock::Milliseconds32(1), [](chip::System::Layer * aSystemLayer, void * aAppState) { @@ -194,6 +209,7 @@ void ChipDeviceEventHandler::HandleCommissioningComplete(const chip::DeviceLayer CHIP_ERROR ChipDeviceEventHandler::SetUdcStatus(bool udcInProgress) { + ChipLogProgress(AppServer, "ChipDeviceEventHandler::SetUdcStatus called with udcInProgress: %d", udcInProgress); if (sUdcInProgress == udcInProgress) { ChipLogError(AppServer, "UDC in progress state is already %d", sUdcInProgress); From 8edcecd7a47da7cd95f49fddcc14ecfa979b3136 Mon Sep 17 00:00:00 2001 From: Sid Hsu Date: Wed, 8 May 2024 22:09:33 +0800 Subject: [PATCH 17/39] [Infineon] Add an example of thermostat for CYW30739. (#33357) --- .github/workflows/examples-infineon.yaml | 26 +++ examples/thermostat/infineon/cyw30739/.gn | 28 +++ .../thermostat/infineon/cyw30739/BUILD.gn | 63 ++++++ .../thermostat/infineon/cyw30739/README.md | 194 ++++++++++++++++++ .../thermostat/infineon/cyw30739/args.gni | 33 +++ .../infineon/cyw30739/build_overrides | 1 + .../infineon/cyw30739/include/AppTask.h | 24 +++ .../cyw30739/include/CHIPProjectConfig.h | 38 ++++ .../infineon/cyw30739/include/SensorManager.h | 41 ++++ .../cyw30739/include/TemperatureManager.h | 56 +++++ .../infineon/cyw30739/include/ThermostatUI.h | 33 +++ .../infineon/cyw30739/src/AppTask.cpp | 90 ++++++++ .../infineon/cyw30739/src/SensorManager.cpp | 84 ++++++++ .../cyw30739/src/TemperatureManager.cpp | 154 ++++++++++++++ .../infineon/cyw30739/src/ThermostatUI.cpp | 63 ++++++ .../infineon/cyw30739/src/ZclCallbacks.cpp | 49 +++++ .../cyw30739/third_party/connectedhomeip | 1 + scripts/build/build/targets.py | 1 + scripts/build/builders/cyw30739.py | 3 + .../build/testdata/all_targets_linux_x64.txt | 2 +- 20 files changed, 983 insertions(+), 1 deletion(-) create mode 100644 examples/thermostat/infineon/cyw30739/.gn create mode 100644 examples/thermostat/infineon/cyw30739/BUILD.gn create mode 100644 examples/thermostat/infineon/cyw30739/README.md create mode 100644 examples/thermostat/infineon/cyw30739/args.gni create mode 120000 examples/thermostat/infineon/cyw30739/build_overrides create mode 100644 examples/thermostat/infineon/cyw30739/include/AppTask.h create mode 100644 examples/thermostat/infineon/cyw30739/include/CHIPProjectConfig.h create mode 100644 examples/thermostat/infineon/cyw30739/include/SensorManager.h create mode 100644 examples/thermostat/infineon/cyw30739/include/TemperatureManager.h create mode 100644 examples/thermostat/infineon/cyw30739/include/ThermostatUI.h create mode 100644 examples/thermostat/infineon/cyw30739/src/AppTask.cpp create mode 100644 examples/thermostat/infineon/cyw30739/src/SensorManager.cpp create mode 100644 examples/thermostat/infineon/cyw30739/src/TemperatureManager.cpp create mode 100644 examples/thermostat/infineon/cyw30739/src/ThermostatUI.cpp create mode 100644 examples/thermostat/infineon/cyw30739/src/ZclCallbacks.cpp create mode 120000 examples/thermostat/infineon/cyw30739/third_party/connectedhomeip diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index 071905d62f0417..68b868c8816305 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -190,6 +190,32 @@ jobs: /tmp/bloat_reports/ - name: Clean out build output run: rm -rf ./out + - name: Build CYW30739 Thermostat App + run: | + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py \ + --target cyw30739-cyw30739b2_p5_evk_01-thermostat \ + --target cyw30739-cyw30739b2_p5_evk_02-thermostat \ + --target cyw30739-cyw30739b2_p5_evk_03-thermostat \ + build \ + --copy-artifacts-to out/artifacts \ + " + - name: Get thermostat size stats + run: | + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + cyw30739 CYW30739B2-P5-EVK-01 thermostat \ + out/artifacts/cyw30739-cyw30739b2_p5_evk_01-thermostat/thermostat-CYW30739B2-P5-EVK-01.elf \ + /tmp/bloat_reports/ + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + cyw30739 CYW30739B2-P5-EVK-02 thermostat \ + out/artifacts/cyw30739-cyw30739b2_p5_evk_02-thermostat/thermostat-CYW30739B2-P5-EVK-02.elf \ + /tmp/bloat_reports/ + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + cyw30739 CYW30739B2-P5-EVK-03 thermostat \ + out/artifacts/cyw30739-cyw30739b2_p5_evk_03-thermostat/thermostat-CYW30739B2-P5-EVK-03.elf \ + /tmp/bloat_reports/ + - name: Clean out build output + run: rm -rf ./out - name: Uploading Size Reports uses: ./.github/actions/upload-size-reports if: ${{ !env.ACT }} diff --git a/examples/thermostat/infineon/cyw30739/.gn b/examples/thermostat/infineon/cyw30739/.gn new file mode 100644 index 00000000000000..90115e4209947e --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "cyw30739" + + import("//args.gni") +} diff --git a/examples/thermostat/infineon/cyw30739/BUILD.gn b/examples/thermostat/infineon/cyw30739/BUILD.gn new file mode 100644 index 00000000000000..b7fae768f08bb0 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/BUILD.gn @@ -0,0 +1,63 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") +import("//build_overrides/cyw30739_sdk.gni") + +import("${chip_root}/examples/platform/infineon/cyw30739/args.gni") +import("${matter_wpan_sdk_build_root}/matter_wpan_executable.gni") + +app_name = "thermostat" +cyw30739_project_dir = "${chip_root}/examples/thermostat/infineon/cyw30739" + +matter_wpan_example("wpan_example") { + sources = [ "${cyw30739_project_dir}/include/CHIPProjectConfig.h" ] + + include_dirs = [ "${cyw30739_project_dir}/include" ] +} + +template("matter_wpan_app") { + forward_variables_from(invoker, [ "board" ]) + + import("${matter_wpan_sdk_build_root}/boards/${board}/args.gni") + + matter_wpan_executable(target_name) { + sources = [ + "src/AppTask.cpp", + "src/SensorManager.cpp", + "src/TemperatureManager.cpp", + "src/ZclCallbacks.cpp", + ] + + if (board_enable_display) { + sources += [ "src/ThermostatUI.cpp" ] + } + + deps = [ app_data_model ] + + include_dirs = [ "include" ] + } +} + +foreach(board, matter_wpan_sdk_board_list) { + matter_wpan_app("${app_name}-${board}") { + } +} + +group("default") { + deps = [] + foreach(board, matter_wpan_sdk_board_list) { + deps += [ ":${app_name}-${board}" ] + } +} diff --git a/examples/thermostat/infineon/cyw30739/README.md b/examples/thermostat/infineon/cyw30739/README.md new file mode 100644 index 00000000000000..44052add4d0ed4 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/README.md @@ -0,0 +1,194 @@ +# Matter CYW30739 Thermostat Example + +An example showing the use of Matter on the Infineon CYW30739 platform. + +--- + +## Table of Contents + +- [Matter CYW30739 Thermostat Example](#matter-cyw30739-thermostat-example) + - [Table of Contents](#table-of-contents) + - [Introduction](#introduction) + - [Installing ModusToolbox™ Software](#installing-modustoolbox-software) + - [ModusToolbox™ tools package](#modustoolbox-tools-package) + - [Note for WSL (Windows Subsystem for Linux)](#note-for-wsl-windows-subsystem-for-linux) + - [Checkout Submodules](#checkout-submodules) + - [Building](#building) + - [Factory Data](#factory-data) + - [Commissionable Data](#commissionable-data) + - [Device Information](#device-information) + - [DAC / DAC Key / PAI Certificate / Certificate Declaration](#dac--dac-key--pai-certificate--certificate-declaration) + - [Flashing the Application](#flashing-the-application) + - [Enter Recovery Mode](#enter-recovery-mode) + - [Run Flash Script](#run-flash-script) + - [Running the Complete Example](#running-the-complete-example) + +--- + +## Introduction + +The CYW30739 thermostat example provides a baseline demonstration of a +thermostat device, built using Matter and the Infineon Modustoolbox SDK. It can +be controlled by a Matter controller over Openthread network. + +The CYW30739 device can be commissioned over Bluetooth Low Energy where the +device and the Matter controller will exchange security information with the +Rendez-vous procedure. Target Thread Network information including the active +dataset and CASE credentials are then provided. + +## Installing [ModusToolbox™ Software](https://www.infineon.com/cms/en/design-support/tools/sdk/modustoolbox-software) + +Follow the +[Installation Guide](https://www.infineon.com/ModusToolboxInstallguide) to +download and install the ModusToolbox™ Software. + +### ModusToolbox™ tools package + +ModusToolbox™ tools package should be automatically installed in the default +location if you followed the +[Installation Guide](https://www.infineon.com/ModusToolboxInstallguide). Please +refer to the Installation Guide for the default location for different operating +systems. + +If you need to install the ModusToolbox™ tools package in a custom location, you +must set the environment variable `CY_TOOLS_PATHS` to the +`/path/to/ModusToolbox/tools_x.x` to specify the location of tools. + +```bash +export CY_TOOLS_PATHS="/path/to/ModusToolbox/tools_x.x" +``` + +#### Note for WSL (Windows Subsystem for Linux) + +If you are using WSL, please ensure you have installed the ModusToolbox™ +Software for Linux. Running Windows tools directly from the WSL command line +would cause path resolution failure in the build process. + +### Checkout Submodules + +Before building the example, check out the Matter repository and sync submodules +using the following command: + +```bash +$ cd ~/connectedhomeip +$ scripts/checkout_submodules.py --platform infineon +``` + +## Building + +- Build the example application: + + ```bash + $ cd ~/connectedhomeip + $ scripts/examples/gn_build_example.sh examples/thermostat/infineon/cyw30739 out/cyw30739-thermostat + ``` + +- OR use GN/Ninja directly + + ```bash + $ cd ~/connectedhomeip + $ source scripts/activate.sh + $ gn gen --root=examples/thermostat/infineon/cyw30739 out/cyw30739-thermostat + $ ninja -C out/cyw30739-thermostat [thermostat-BOARD_NAME] + ``` + +- To delete generated executable, libraries and object files use: + + ```bash + $ cd ~/connectedhomeip + $ rm -rf out/cyw30739-thermostat + ``` + +## Factory Data + +### Commissionable Data + +Infineon CYW30739 examples use test passcode, discriminator and PAKE parameters +by default. For a production build, manufacturers should override commissionable +data by the following arguments: + +- `matter_passcode`, `matter_discriminator`, `matter_pake_iteration_count`, + `matter_pake_salt` + + ```bash + $ cd ~/connectedhomeip + $ scripts/examples/gn_build_example.sh examples/thermostat/infineon/cyw30739 out/cyw30739-thermostat \ + 'matter_passcode=20202021' \ + 'matter_discriminator=3840' \ + 'matter_pake_iteration_count=1000' \ + 'matter_pake_salt="U1BBS0UyUCBLZXkgU2FsdA=="' + ``` + +### Device Information + +Infineon CYW30739 examples support overriding the default device information by +the following arguments: + +- matter_vendor_name +- matter_vendor_id +- matter_product_name +- matter_product_id +- matter_serial_number +- matter_hardware_version +- matter_hardware_version_string + +To override the default device information, pass the desired values to the +`gn_build_example.sh` script as arguments. + + ```bash + $ cd ~/connectedhomeip + $ scripts/examples/gn_build_example.sh examples/thermostat/infineon/cyw30739 out/cyw30739-thermostat \ + 'matter_vendor_name="Infineon"' \ + 'matter_vendor_id="0x1388"' \ + 'matter_product_name="TEST_PRODUCT"' \ + 'matter_product_id="0x0001"' \ + 'matter_serial_number="TEST_SN"' \ + 'matter_hardware_version=30739' \ + 'matter_hardware_version_string="30739"' + ``` + +### DAC / DAC Key / PAI Certificate / Certificate Declaration + +Infineon CYW30739 examples use development certifications, keys, and CD by +default. For a production build, manufacturers can provision certifications, +keys, and CD by the following arguments: + +- `matter_att_cert`, `matter_att_cert_password`, `matter_cd` + + ```bash + $ cd ~/connectedhomeip + $ scripts/examples/gn_build_example.sh examples/thermostat/infineon/cyw30739 out/cyw30739-thermostat \ + 'matter_att_cert="/path/to/att_cert.p12"' \ + 'matter_att_cert_password="password"' \ + 'matter_cd="/path/to/cd.der"' + ``` + +## Flashing the Application + +### Enter Recovery Mode + +Put the CYW30739 in to the recovery mode before running the flash script. + +1. Press and hold the `RECOVERY` button on the board. +2. Press and hold the `RESET` button on the board. +3. Release the `RESET` button. +4. After one second, release the `RECOVERY` button. + +### Run Flash Script + +- On the command line: + + ```bash + $ cd ~/connectedhomeip + $ out/cyw30739-thermostat/thermostat-BOARD_NAME.flash.py --port + ``` + +## Running the Complete Example + +- It is assumed here that you already have an OpenThread border router + configured and running. If not see the following guide + [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md) + for more information on how to setup a border router on a raspberryPi. + +- For this example to work, it is necessary to have a second CYW30739 device + running the thermostat example commissioned on the same OpenThread network diff --git a/examples/thermostat/infineon/cyw30739/args.gni b/examples/thermostat/infineon/cyw30739/args.gni new file mode 100644 index 00000000000000..88c48b5b1a1f5e --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/args.gni @@ -0,0 +1,33 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# 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. + +import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") +import("${chip_root}/src/platform/Infineon/CYW30739/args.gni") + +app_data_model = "${chip_root}/examples/thermostat/thermostat-common" + +chip_openthread_ftd = false +chip_enable_icd_server = true +chip_enable_ota_requestor = true + +matter_product_id = "0x0006" +matter_product_name = "CYW30739 Thermostat App" +matter_att_cert = "${chip_root}/examples/platform/infineon/credentials/development/attestation/Matter-Development-DAC-1388-0006.p12" + +matter_wpan_sdk_board_list = [ + "CYW30739B2-P5-EVK-01", + "CYW30739B2-P5-EVK-02", + "CYW30739B2-P5-EVK-03", +] diff --git a/examples/thermostat/infineon/cyw30739/build_overrides b/examples/thermostat/infineon/cyw30739/build_overrides new file mode 120000 index 00000000000000..995884e6163eb5 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/build_overrides @@ -0,0 +1 @@ +../../../build_overrides \ No newline at end of file diff --git a/examples/thermostat/infineon/cyw30739/include/AppTask.h b/examples/thermostat/infineon/cyw30739/include/AppTask.h new file mode 100644 index 00000000000000..d71018ffb07cba --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/include/AppTask.h @@ -0,0 +1,24 @@ +/* + * + * Copyright (c) 2022 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 + +void AppTaskMain(intptr_t args); +void UpdateThermoStatUI(intptr_t aArg); diff --git a/examples/thermostat/infineon/cyw30739/include/CHIPProjectConfig.h b/examples/thermostat/infineon/cyw30739/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..d0e3c7dce66c9a --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/include/CHIPProjectConfig.h @@ -0,0 +1,38 @@ +/* + * + * Copyright (c) 2022 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. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#pragma once + +// -------------------- Device Identification Configuration -------------------- +/* The SoftwareVersionString attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "1.3.1.327" + +/* The SoftwareVersion attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x00130547 + +// -------------------- Test Configuration -------------------- +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 diff --git a/examples/thermostat/infineon/cyw30739/include/SensorManager.h b/examples/thermostat/infineon/cyw30739/include/SensorManager.h new file mode 100644 index 00000000000000..fad73f7661935c --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/include/SensorManager.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2022 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 + +using namespace chip::DeviceLayer; + +class SensorManager +{ +public: + void Init(AsyncWorkFunct interruptHandler); + +private: + static void InterruptHandler(void * data, uint8_t port_pin); + + friend SensorManager & SensorMgr(); + static SensorManager sSensorManager; + static AsyncWorkFunct sAppInterruptHandler; +}; + +inline SensorManager & SensorMgr() +{ + return SensorManager::sSensorManager; +} diff --git a/examples/thermostat/infineon/cyw30739/include/TemperatureManager.h b/examples/thermostat/infineon/cyw30739/include/TemperatureManager.h new file mode 100644 index 00000000000000..cd82f2c80f6c7f --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/include/TemperatureManager.h @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2022 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 + +#include + +using namespace chip; +using namespace ::chip::app::Clusters::Thermostat; + +class TemperatureManager +{ +public: + CHIP_ERROR Init(); + void SensorInterruptHandler(); + void AttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size); + SystemModeEnum GetMode(); + int16_t GetCurrentTemp(); + uint8_t GetCurrentHumidity(); + int8_t GetHeatingSetPoint(); + int8_t GetCoolingSetPoint(); + +private: + friend TemperatureManager & TempMgr(); + + int8_t mCurrentTempCelsius; + uint8_t mCurrentHumidity; + int8_t mCoolingCelsiusSetPoint; + int8_t mHeatingCelsiusSetPoint; + SystemModeEnum mThermMode; + + int8_t ConvertToPrintableTemp(int16_t temperature); + static TemperatureManager sTempMgr; +}; + +inline TemperatureManager & TempMgr() +{ + return TemperatureManager::sTempMgr; +} diff --git a/examples/thermostat/infineon/cyw30739/include/ThermostatUI.h b/examples/thermostat/infineon/cyw30739/include/ThermostatUI.h new file mode 100644 index 00000000000000..1da4f7f831e176 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/include/ThermostatUI.h @@ -0,0 +1,33 @@ +/* + * + * Copyright (c) 2020 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 + +class ThermostatUI +{ +public: + static void DrawUI(); + static void SetCurrentTemp(int8_t temp); + static void SetCurrentHumidity(uint8_t humidity); + +private: + static void DrawCurrentTemp(int8_t temp); + static void DrawCurrentHumidity(uint8_t humidity); +}; diff --git a/examples/thermostat/infineon/cyw30739/src/AppTask.cpp b/examples/thermostat/infineon/cyw30739/src/AppTask.cpp new file mode 100644 index 00000000000000..050c72c62f7b18 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/src/AppTask.cpp @@ -0,0 +1,90 @@ +/* + * + * Copyright (c) 2022 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 "AppTask.h" +#include "SensorManager.h" +#include "TemperatureManager.h" +#ifdef BOARD_ENABLE_DISPLAY +#include "ThermostatUI.h" +#endif +#include +#include +#include + +using namespace chip::app; + +static void SensorInterruptHandler(intptr_t aArg); + +void AppTaskMain(intptr_t args) +{ + SensorMgr().Init(SensorInterruptHandler); + if (TempMgr().Init() != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "TempMgr Init fail"); + } + + CYW30739MatterConfig::InitApp(); +} + +void UpdateThermoStatUI(intptr_t aArg) +{ +#ifdef BOARD_ENABLE_DISPLAY + ThermostatUI::SetCurrentTemp(TempMgr().GetCurrentTemp()); + ThermostatUI::SetCurrentHumidity(TempMgr().GetCurrentHumidity()); + ThermostatUI::DrawUI(); +#endif + ChipLogDetail(Zcl, "Thermostat Status - M:%d Temp:%d'C Humidity:%d'C H:%d'C C:%d'C", to_underlying(TempMgr().GetMode()), + TempMgr().GetCurrentTemp(), TempMgr().GetCurrentHumidity(), TempMgr().GetHeatingSetPoint(), + TempMgr().GetCoolingSetPoint()); +} + +void SensorInterruptHandler(intptr_t aArg) +{ + TempMgr().SensorInterruptHandler(); + UpdateThermoStatUI(aArg); +} + +void OnIdentifyTriggerEffect(Identify * identify) +{ + switch (identify->mCurrentEffectIdentifier) + { + case Clusters::Identify::EffectIdentifierEnum::kBlink: + ChipLogProgress(Zcl, "Clusters::Identify::EffectIdentifierEnum::kBlink"); + break; + case Clusters::Identify::EffectIdentifierEnum::kBreathe: + ChipLogProgress(Zcl, "Clusters::Identify::EffectIdentifierEnum::kBreathe"); + break; + case Clusters::Identify::EffectIdentifierEnum::kOkay: + ChipLogProgress(Zcl, "Clusters::Identify::EffectIdentifierEnum::kOkay"); + break; + case Clusters::Identify::EffectIdentifierEnum::kChannelChange: + ChipLogProgress(Zcl, "Clusters::Identify::EffectIdentifierEnum::kChannelChange"); + break; + default: + ChipLogProgress(Zcl, "No identifier effect"); + break; + } +} + +static Identify gIdentify = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + Clusters::Identify::IdentifyTypeEnum::kNone, + OnIdentifyTriggerEffect, +}; diff --git a/examples/thermostat/infineon/cyw30739/src/SensorManager.cpp b/examples/thermostat/infineon/cyw30739/src/SensorManager.cpp new file mode 100644 index 00000000000000..6e81016beb86b5 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/src/SensorManager.cpp @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2022 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. + */ + +/********************************************************** + * Includes + *********************************************************/ + +#include "SensorManager.h" +#include "AppTask.h" +#include "hdc2010.h" +#include "wiced_hal_gpio.h" +#include +#include + +#define HDC2010_ADDR 0x40 + +/* Calibration */ +#define TEMPERATURE_CALIBRATION 0xEA +#define HUMIDITY_CALIBRATION 0x0B + +/********************************************************** + * Defines and Constants + *********************************************************/ + +using namespace chip; +using namespace ::chip::DeviceLayer; + +/********************************************************** + * Variable declarations + *********************************************************/ + +SensorManager SensorManager::sSensorManager; +AsyncWorkFunct SensorManager::sAppInterruptHandler = nullptr; + +void SensorManager::Init(AsyncWorkFunct interruptHandler) +{ + wiced_hdc2010_address(HDC2010_ADDR); + + // Begin with a device reset + wiced_hdc2010_reset(); + + // Configure interrupt pin + wiced_hdc2010_enable_interrupt(); // Enable the Interrupt/DRDY pin + wiced_hdc2010_set_interrupt_polarity(WICED_HDC2010_ACTIVE_HIGH); // Set Interrupt pin to Active High + wiced_hdc2010_set_interrupt_mode(WICED_HDC2010_LEVEL_MODE); // Set Interrupt to return to inactive state when in bounds + wiced_hdc2010_enable_DRDY_interrupt(); + + // Configure Measurements + wiced_hdc2010_set_measurement_mode(WICED_HDC2010_TEMP_AND_HUMID); // Set measurements to temperature and humidity + wiced_hdc2010_set_rate(WICED_HDC2010_TEN_SECONDS); + wiced_hdc2010_set_temp_res(WICED_HDC2010_FOURTEEN_BIT); + wiced_hdc2010_set_humid_res(WICED_HDC2010_FOURTEEN_BIT); + wiced_hdc2010_temp_adjust(TEMPERATURE_CALIBRATION); + wiced_hdc2010_humidity_adjust(HUMIDITY_CALIBRATION); + + wiced_hal_gpio_register_pin_for_interrupt(PLATFORM_SENSOR_INT, InterruptHandler, NULL); + // begin measuring + wiced_hdc2010_trigger_measurement(); + + sAppInterruptHandler = interruptHandler; +} + +void SensorManager::InterruptHandler(void * data, uint8_t port_pin) +{ + if (sAppInterruptHandler != nullptr) + { + PlatformMgr().ScheduleWork(sAppInterruptHandler); + } +} diff --git a/examples/thermostat/infineon/cyw30739/src/TemperatureManager.cpp b/examples/thermostat/infineon/cyw30739/src/TemperatureManager.cpp new file mode 100644 index 00000000000000..57d0e02d3d777c --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/src/TemperatureManager.cpp @@ -0,0 +1,154 @@ +/* + * + * Copyright (c) 2022 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. + */ + +/********************************************************** + * Includes + *********************************************************/ + +#include "TemperatureManager.h" +#include "AppTask.h" +#include "hdc2010.h" +#include "platform/CHIPDeviceLayer.h" + +/********************************************************** + * Defines and Constants + *********************************************************/ + +using namespace chip; +using namespace ::chip::DeviceLayer; + +constexpr EndpointId kThermostatEndpoint = 1; + +using namespace ::chip::app::Clusters::Thermostat; +namespace ThermAttr = chip::app::Clusters::Thermostat::Attributes; +/********************************************************** + * Variable declarations + *********************************************************/ + +TemperatureManager TemperatureManager::sTempMgr; + +CHIP_ERROR TemperatureManager::Init() +{ + app::DataModel::Nullable temp; + int16_t heatingSetpoint, coolingSetpoint; + + ThermAttr::LocalTemperature::Get(kThermostatEndpoint, temp); + ThermAttr::OccupiedCoolingSetpoint::Get(kThermostatEndpoint, &coolingSetpoint); + ThermAttr::OccupiedHeatingSetpoint::Get(kThermostatEndpoint, &heatingSetpoint); + ThermAttr::SystemMode::Get(kThermostatEndpoint, &mThermMode); + + mCurrentTempCelsius = 0; + mCurrentHumidity = 0; + mHeatingCelsiusSetPoint = ConvertToPrintableTemp(coolingSetpoint); + mCoolingCelsiusSetPoint = ConvertToPrintableTemp(heatingSetpoint); + + return CHIP_NO_ERROR; +} + +void TemperatureManager::SensorInterruptHandler() +{ + ThermAttr::LocalTemperature::Set(kThermostatEndpoint, wiced_hdc2010_read_temp() * 100); + + mCurrentHumidity = wiced_hdc2010_read_humidity(); +} + +int8_t TemperatureManager::ConvertToPrintableTemp(int16_t temperature) +{ + constexpr uint8_t kRoundUpValue = 50; + + // Round up the temperature as we won't print decimals on LCD + // Is it a negative temperature + if (temperature < 0) + { + temperature -= kRoundUpValue; + } + else + { + temperature += kRoundUpValue; + } + + return static_cast(temperature / 100); +} + +void TemperatureManager::AttributeChangeHandler(EndpointId endpointId, AttributeId attributeId, uint8_t * value, uint16_t size) +{ + switch (attributeId) + { + case ThermAttr::LocalTemperature::Id: { + int8_t Temp = ConvertToPrintableTemp(*((int16_t *) value)); + ChipLogDetail(Zcl, "Local temp %d", Temp); + mCurrentTempCelsius = Temp; + } + break; + + case ThermAttr::OccupiedCoolingSetpoint::Id: { + int8_t coolingTemp = ConvertToPrintableTemp(*((int16_t *) value)); + ChipLogDetail(Zcl, "CoolingSetpoint %d", coolingTemp); + mCoolingCelsiusSetPoint = coolingTemp; + } + break; + + case ThermAttr::OccupiedHeatingSetpoint::Id: { + int8_t heatingTemp = ConvertToPrintableTemp(*((int16_t *) value)); + ChipLogDetail(Zcl, "HeatingSetpoint %d", heatingTemp); + mHeatingCelsiusSetPoint = heatingTemp; + } + break; + + case ThermAttr::SystemMode::Id: { + ChipLogDetail(Zcl, "SystemMode %d", static_cast(*value)); + SystemModeEnum mode = static_cast(*value); + if (mThermMode != mode) + { + mThermMode = mode; + } + } + break; + + default: { + ChipLogDetail(Zcl, "Unhandled thermostat attribute %lx", attributeId); + return; + } + break; + } +} + +SystemModeEnum TemperatureManager::GetMode() +{ + return mThermMode; +} + +int16_t TemperatureManager::GetCurrentTemp() +{ + return mCurrentTempCelsius; +} + +uint8_t TemperatureManager::GetCurrentHumidity() +{ + return mCurrentHumidity; +} + +int8_t TemperatureManager::GetHeatingSetPoint() +{ + return mHeatingCelsiusSetPoint; +} + +int8_t TemperatureManager::GetCoolingSetPoint() +{ + return mCoolingCelsiusSetPoint; +} diff --git a/examples/thermostat/infineon/cyw30739/src/ThermostatUI.cpp b/examples/thermostat/infineon/cyw30739/src/ThermostatUI.cpp new file mode 100644 index 00000000000000..420b261641014c --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/src/ThermostatUI.cpp @@ -0,0 +1,63 @@ +/* + * + * Copyright (c) 2020 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 "ThermostatUI.h" +#include "GUI.h" +#include + +static int8_t mCurrentTempCelsius; +static uint8_t mCurrentHumidity; + +void ThermostatUI::DrawUI() +{ + GUI_SetBkColor(GUI_BLACK); + GUI_Clear(); + DrawCurrentTemp(mCurrentTempCelsius); + DrawCurrentHumidity(mCurrentHumidity); +} + +void ThermostatUI::SetCurrentTemp(int8_t temp) +{ + mCurrentTempCelsius = temp; +} + +void ThermostatUI::SetCurrentHumidity(uint8_t humidity) +{ + mCurrentHumidity = humidity; +} + +void ThermostatUI::DrawCurrentTemp(int8_t temp) +{ + char buffer[8]; + sprintf(buffer, "%d", temp); + GUI_DrawCircle(31, 31, 31); + GUI_SetFont(&GUI_Font24B_1); + GUI_DispStringAt(buffer, 10, 22); + GUI_DispChar(176); // degree + GUI_DispChar('C'); +} + +void ThermostatUI::DrawCurrentHumidity(uint8_t humidity) +{ + char buffer[8]; + sprintf(buffer, "%d", humidity); + GUI_DrawCircle(96, 31, 31); + GUI_SetFont(&GUI_Font24B_1); + GUI_DispStringAt(buffer, 78, 22); + GUI_DispChar('%'); +} diff --git a/examples/thermostat/infineon/cyw30739/src/ZclCallbacks.cpp b/examples/thermostat/infineon/cyw30739/src/ZclCallbacks.cpp new file mode 100644 index 00000000000000..5965eadf631176 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/src/ZclCallbacks.cpp @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2022 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. + */ + +/** + * @file + * This file implements the handler for data model messages. + */ + +#include "TemperatureManager.h" +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app::Clusters; + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, + uint8_t * value) +{ + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId)); + + if (clusterId == Identify::Id) + { + ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u", + ChipLogValueMEI(attributeId), type, *value, size); + } + else if (clusterId == Thermostat::Id) + { + TempMgr().AttributeChangeHandler(attributePath.mEndpointId, attributeId, value, size); + } +} diff --git a/examples/thermostat/infineon/cyw30739/third_party/connectedhomeip b/examples/thermostat/infineon/cyw30739/third_party/connectedhomeip new file mode 120000 index 00000000000000..59307833b4fee9 --- /dev/null +++ b/examples/thermostat/infineon/cyw30739/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../.. \ No newline at end of file diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index bf797220032b15..aff2fac037d52b 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -551,6 +551,7 @@ def BuildCyw30739Target(): TargetPart('light', app=Cyw30739App.LIGHT), TargetPart('light-switch', app=Cyw30739App.LIGHT_SWITCH), TargetPart('lock', app=Cyw30739App.LOCK), + TargetPart('thermostat', app=Cyw30739App.THERMOSTAT), ]) return target diff --git a/scripts/build/builders/cyw30739.py b/scripts/build/builders/cyw30739.py index 41bfecc10fd789..4c03edca3151ef 100644 --- a/scripts/build/builders/cyw30739.py +++ b/scripts/build/builders/cyw30739.py @@ -22,6 +22,7 @@ class Cyw30739App(Enum): LIGHT = auto() LIGHT_SWITCH = auto() LOCK = auto() + THERMOSTAT = auto() def ExampleName(self): if self == Cyw30739App.LIGHT: @@ -30,6 +31,8 @@ def ExampleName(self): return "light-switch-app" elif self == Cyw30739App.LOCK: return "lock-app" + elif self == Cyw30739App.THERMOSTAT: + return "thermostat" else: raise Exception("Unknown app type: %r" % self) diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index aff956fa31edc2..de45fdb9d8ba77 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -4,7 +4,7 @@ android-{arm,arm64,x86,x64,androidstudio-arm,androidstudio-arm64,androidstudio-x bouffalolab-{bl602-iot-matter-v1,bl602-night-light,xt-zb6-devkit,bl706-night-light,bl706dk,bl704ldk}-light[-shell][-115200][-rpc][-cdc][-resetcnt][-rotating_device_id][-mfd][-mfdtest][-ethernet][-wifi][-thread][-fp][-memmonitor][-mot] cc32xx-{lock,air-purifier} ti-cc13x4_26x4-{all-clusters,lighting,lock,pump,pump-controller}[-mtd][-ftd] -cyw30739-{cyw30739b2_p5_evk_01,cyw30739b2_p5_evk_02,cyw30739b2_p5_evk_03,cyw930739m2evb_01,cyw930739m2evb_02}-{light,light-switch,lock} +cyw30739-{cyw30739b2_p5_evk_01,cyw30739b2_p5_evk_02,cyw30739b2_p5_evk_03,cyw930739m2evb_01,cyw930739m2evb_02}-{light,light-switch,lock,thermostat} efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,brd4304a,brd4338a}-{window-covering,switch,unit-test,light,lock,thermostat,pump}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation] 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] genio-lighting-app From 0259b9adf092a4b2d1137b411e32ecc96f1bb12b Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Wed, 8 May 2024 18:15:00 -0400 Subject: [PATCH 18/39] Fix efr32 assert due to missing init, renable RTT logs with pw-rcp enable. Temporaly remove TestExchange from efr32 (#33375) --- src/messaging/tests/BUILD.gn | 4 +++- src/platform/silabs/Logging.cpp | 8 ++++---- src/test_driver/efr32/src/main.cpp | 2 ++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/messaging/tests/BUILD.gn b/src/messaging/tests/BUILD.gn index 0e56444ba40952..a78dcce953756b 100644 --- a/src/messaging/tests/BUILD.gn +++ b/src/messaging/tests/BUILD.gn @@ -49,13 +49,15 @@ static_library("helpers") { chip_test_suite_using_nltest("tests") { output_name = "libMessagingLayerTests" - test_sources = [ "TestExchange.cpp" ] + test_sources = [] if (chip_device_platform != "efr32") { # TODO(#10447): ReliableMessage Test has HF, and ExchangeMgr hangs on EFR32. # And TestAbortExchangesForFabric does not link on EFR32 for some reason. + # TODO #33372: TestExchange.cpp asserts in ExchangeContext::SendMessage test_sources += [ "TestAbortExchangesForFabric.cpp", + "TestExchange.cpp", "TestExchangeMgr.cpp", "TestReliableMessageProtocol.cpp", ] diff --git a/src/platform/silabs/Logging.cpp b/src/platform/silabs/Logging.cpp index 71f377f94e66e3..3777c96148fb75 100644 --- a/src/platform/silabs/Logging.cpp +++ b/src/platform/silabs/Logging.cpp @@ -136,9 +136,10 @@ static void PrintLog(const char * msg) #if SILABS_LOG_OUT_UART uartLogWrite(msg, sz); -#elif PW_RPC_ENABLED - PigweedLogger::putString(msg, sz); #else +#if PW_RPC_ENABLED + PigweedLogger::putString(msg, sz); +#endif // PW_RPC_ENABLED SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, msg, sz); #endif // SILABS_LOG_OUT_UART @@ -147,9 +148,8 @@ static void PrintLog(const char * msg) sz = strlen(newline); #if PW_RPC_ENABLED PigweedLogger::putString(newline, sz); -#else - SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, newline, sz); #endif // PW_RPC_ENABLED + SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, newline, sz); #endif } } diff --git a/src/test_driver/efr32/src/main.cpp b/src/test_driver/efr32/src/main.cpp index 52015048ee842a..57d0bab32b940b 100644 --- a/src/test_driver/efr32/src/main.cpp +++ b/src/test_driver/efr32/src/main.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -185,6 +186,7 @@ void RunRpcService(void *) int main(void) { + sl_system_init(); chip::DeviceLayer::Silabs::GetPlatform().Init(); PigweedLogger::init(); mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); From 1dd94951deb2cd857d98e64c51e9da9a7dc59656 Mon Sep 17 00:00:00 2001 From: Shao Ling Tan <161761051+shaoltan-amazon@users.noreply.github.com> Date: Wed, 8 May 2024 18:18:50 -0700 Subject: [PATCH 19/39] [Linux] Add test logic to verify that launchURL is sent from Linux tv-casting-app to Linux tv-app. (#33344) --- scripts/tests/run_tv_casting_test.py | 89 +++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/scripts/tests/run_tv_casting_test.py b/scripts/tests/run_tv_casting_test.py index ea0fc244b99049..c2492c5cb8818d 100644 --- a/scripts/tests/run_tv_casting_test.py +++ b/scripts/tests/run_tv_casting_test.py @@ -33,6 +33,9 @@ # The maximum amount of time to commission the Linux tv-casting-app and the tv-app before timeout. COMMISSIONING_STAGE_MAX_WAIT_SEC = 10 +# The maximum amount of time to test that the launchURL is sent from the Linux tv-casting-app and received on the tv-app before timeout. +TEST_LAUNCHURL_MAX_WAIT_SEC = 10 + # File names of logs for the Linux tv-casting-app and the Linux tv-app. LINUX_TV_APP_LOGS = 'Linux-tv-app-logs.txt' LINUX_TV_CASTING_APP_LOGS = 'Linux-tv-casting-app-logs.txt' @@ -303,10 +306,80 @@ def validate_commissioning_success(tv_casting_app_info: Tuple[subprocess.Popen, if 'PROMPT USER: commissioning success' in tv_app_line: logging.info('Commissioning success noted on the Linux tv-app output:') + logging.info(tv_app_line) + return True + + +def parse_tv_app_output_for_launchUrl_msg_success(tv_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]): + """Parse the Linux tv-app output for the relevant string indicating that the launchUrl was received.""" + + tv_app_process, linux_tv_app_log_file = tv_app_info + + start_wait_time = time.time() + + while True: + # Check if we exceeded the maximum wait time to parse the Linux tv-app output for the string related to the launchUrl. + if time.time() - start_wait_time > COMMISSIONING_STAGE_MAX_WAIT_SEC: + logging.error( + 'The relevant launchUrl string was not found in the Linux tv-app process within the timeout.') + return False + + tv_app_line = tv_app_process.stdout.readline() + + if tv_app_line: + linux_tv_app_log_file.write(tv_app_line) + linux_tv_app_log_file.flush() + + if 'ContentLauncherManager::HandleLaunchUrl TEST CASE ContentURL=https://www.test.com/videoid DisplayString=Test video' in tv_app_line: + logging.info('Found the launchUrl in the Linux tv-app output:') logging.info(tv_app_line.rstrip('\n')) return True +def parse_tv_casting_app_output_for_launchUrl_msg_success(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]): + """Parse the Linux tv-casting-app output for relevant strings indicating that the launchUrl was sent.""" + + tv_casting_app_process, linux_tv_casting_app_log_file = tv_casting_app_info + + continue_parsing_invoke_response_msg_block = False + found_example_data_msg = False + start_wait_time = time.time() + + while True: + # Check if we exceeded the maximum wait time to parse the Linux tv-casting-app output for strings related to the launchUrl. + if time.time() - start_wait_time > TEST_LAUNCHURL_MAX_WAIT_SEC: + logging.error( + 'The relevant launchUrl strings were not found in the Linux tv-casting-app process within the timeout.') + return False + + tv_casting_line = tv_casting_app_process.stdout.readline() + + if tv_casting_line: + linux_tv_casting_app_log_file.write(tv_casting_line) + linux_tv_casting_app_log_file.flush() + + if 'InvokeResponseMessage =' in tv_casting_line: + logging.info('Found the InvokeResponseMessage block in the Linux tv-casting-app output:') + logging.info(tv_casting_line.rstrip('\n')) + continue_parsing_invoke_response_msg_block = True + + elif continue_parsing_invoke_response_msg_block: + # Sanity check for `exampleData` in the `InvokeResponseMessage` block. + if 'exampleData' in tv_casting_line: + found_example_data_msg = True + + elif 'Received Command Response Data' in tv_casting_line: + if not found_example_data_msg: + logging.error('The `exampleData` string was not found in the `InvokeResponseMessage` block.') + return False + + logging.info('Found the `Received Command Response Data` string in the Linux tv-casting-app output:') + logging.info(tv_casting_line.rstrip('\n')) + return True + + logging.info(tv_casting_line.rstrip('\n')) + + def test_discovery_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]) -> Optional[str]: """Parse the output of the Linux tv-casting-app to find a valid commissioner.""" tv_casting_app_process, linux_tv_casting_app_log_file = tv_casting_app_info @@ -347,7 +420,7 @@ def test_discovery_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], log_ logging.info(valid_vendor_id) logging.info(valid_product_id) logging.info(valid_device_type) - logging.info('Discovery success!') + logging.info('Discovery success!\n') break return valid_discovered_commissioner @@ -372,6 +445,18 @@ def test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_i handle_casting_failure('Commissioning', log_paths) +def test_launchUrl_fn(tv_casting_app_info: Tuple[subprocess.Popen, TextIO], tv_app_info: Tuple[subprocess.Popen, TextIO], log_paths: List[str]): + """Test that the Linux tv-casting-app sent the launchUrl and that the Linux tv-app received the launchUrl.""" + + if not parse_tv_app_output_for_launchUrl_msg_success(tv_app_info, log_paths): + handle_casting_failure('Testing launchUrl', log_paths) + + if not parse_tv_casting_app_output_for_launchUrl_msg_success(tv_casting_app_info, log_paths): + handle_casting_failure('Testing launchUrl', log_paths) + + logging.info('Testing launchUrl success!\n') + + @click.command() @click.option('--tv-app-rel-path', type=str, default='out/tv-app/chip-tv-app', help='Path to the Linux tv-app executable.') @click.option('--tv-casting-app-rel-path', type=str, default='out/tv-casting-app/chip-tv-casting-app', help='Path to the Linux tv-casting-app executable.') @@ -420,6 +505,8 @@ def test_casting_fn(tv_app_rel_path, tv_casting_app_rel_path): test_commissioning_fn(valid_discovered_commissioner_number, tv_casting_app_info, tv_app_info, log_paths) + test_launchUrl_fn(tv_casting_app_info, tv_app_info, log_paths) + if __name__ == '__main__': From e079364d2f18aae6c4718cd7074ea62fae3f0360 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Thu, 9 May 2024 16:19:44 +0900 Subject: [PATCH 20/39] [Android][ICD]Implement Android ICD sending using buffer (#33377) * Implement Android ICD Queue sending * Kotlin detect config --- .../clusterclient/AddressUpdateFragment.kt | 27 ++++- .../clusterclient/WildcardFragment.kt | 112 +++++++++++++++--- kotlin-detect-config.yaml | 1 + 3 files changed, 119 insertions(+), 21 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt index 1fa6fadcff9ed3..43eeb2b892c51c 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/AddressUpdateFragment.kt @@ -21,7 +21,6 @@ import com.google.chip.chiptool.ChipClient import com.google.chip.chiptool.databinding.AddressUpdateFragmentBinding import com.google.chip.chiptool.util.DeviceIdUtil import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -55,6 +54,8 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() { private val handler = Handler(Looper.getMainLooper()) + private var externalICDCheckInMessageCallback: ICDCheckInMessageCallback? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -128,11 +129,12 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() { } val cluster = ChipClusters.IcdManagementCluster(devicePtr, 0) - val duration = suspendCoroutine { cont -> + val retDuration = suspendCoroutine { cont -> cluster.stayActiveRequest( object : ChipClusters.IcdManagementCluster.StayActiveResponseCallback { override fun onError(error: Exception) { - cont.resumeWithException(error) + Log.d(TAG, "onError", error) + cont.resume(0L) } override fun onSuccess(promisedActiveDuration: Long) { @@ -143,12 +145,11 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() { ) } isSendingStayActiveCommand = false - return duration + return retDuration } private fun updateUIForICDInteractionSwitch(isEnabled: Boolean): Boolean { - val isICD = - deviceController.icdClientInfo.firstOrNull { info -> info.peerNodeId == deviceId } != null + val isICD = isICDDevice() if (isEnabled && !isICD) { binding.icdInteractionSwitch.isChecked = false return false @@ -188,7 +189,13 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() { return binding.deviceIdEd.text.toString().toULong(16) } + fun isICDDevice(): Boolean { + return deviceController.icdClientInfo.firstOrNull { info -> info.peerNodeId == deviceId } != + null + } + override fun notifyCheckInMessage(info: ICDClientInfo) { + externalICDCheckInMessageCallback?.notifyCheckInMessage() if (info.peerNodeId != icdDeviceId) { return } @@ -206,6 +213,14 @@ class AddressUpdateFragment : ICDCheckInCallback, Fragment() { } } + fun setNotifyCheckInMessageCallback(callback: ICDCheckInMessageCallback?) { + externalICDCheckInMessageCallback = callback + } + + interface ICDCheckInMessageCallback { + fun notifyCheckInMessage() + } + private fun turnOnActiveMode() { requireActivity().runOnUiThread { binding.icdProgressBar.max = (icdTotalRemainStayActiveTimeMs / 1000).toInt() diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index 2ffbec50c746a2..4324ba535d886a 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -45,7 +45,7 @@ import matter.tlv.AnonymousTag import matter.tlv.TlvReader import matter.tlv.TlvWriter -class WildcardFragment : Fragment() { +class WildcardFragment : Fragment(), AddressUpdateFragment.ICDCheckInMessageCallback { private var _binding: WildcardFragmentBinding? = null private val binding get() = _binding!! @@ -63,6 +63,23 @@ class WildcardFragment : Fragment() { private val invokePath = ArrayList() private val subscribeIdList = ArrayList() + data class ReadICDConfig(val isFabricFiltered: Boolean, val eventMin: Long?) + + data class SubscribeICDConfig( + val minInterval: Int, + val maxInterval: Int, + val keepSubscriptions: Boolean, + val isFabricFiltered: Boolean, + val eventMin: Long? + ) + + data class WriteInvokeICDConfig(val timedRequestTimeoutMs: Int, val imTimeoutMs: Int) + + private var readICDConfig: ReadICDConfig? = null + private var subscribeICDConfig: SubscribeICDConfig? = null + private var writeICDConfig: WriteInvokeICDConfig? = null + private var invokeICDConfig: WriteInvokeICDConfig? = null + private val reportCallback = object : ReportCallback { override fun onError( @@ -173,6 +190,45 @@ class WildcardFragment : Fragment() { return binding.root } + override fun onResume() { + super.onResume() + addressUpdateFragment.setNotifyCheckInMessageCallback(this) + } + + override fun onPause() { + addressUpdateFragment.setNotifyCheckInMessageCallback(null) + super.onPause() + } + + override fun notifyCheckInMessage() { + Log.d(TAG, "notifyCheckInMessage") + if (attributePath.isNotEmpty() || eventPath.isNotEmpty()) { + if (binding.readRadioBtn.isChecked && readICDConfig != null) { + scope.launch { read(readICDConfig!!.isFabricFiltered, readICDConfig!!.eventMin) } + } else if (binding.subscribeRadioBtn.isChecked && subscribeICDConfig != null) { + scope.launch { + subscribe( + subscribeICDConfig!!.minInterval, + subscribeICDConfig!!.maxInterval, + subscribeICDConfig!!.keepSubscriptions, + subscribeICDConfig!!.isFabricFiltered, + subscribeICDConfig!!.eventMin + ) + } + } + } else if ( + binding.writeRadioBtn.isChecked && writePath.isNotEmpty() && writeICDConfig != null + ) { + scope.launch { write(writeICDConfig!!.timedRequestTimeoutMs, writeICDConfig!!.imTimeoutMs) } + } else if ( + binding.invokeRadioBtn.isChecked && invokePath.isNotEmpty() && invokeICDConfig != null + ) { + scope.launch { + invoke(invokeICDConfig!!.timedRequestTimeoutMs, invokeICDConfig!!.imTimeoutMs) + } + } + } + private fun setVisibilityEachView(radioBtnId: Int) { val readBtnOn = (radioBtnId == R.id.readRadioBtn) val subscribeBtnOn = (radioBtnId == R.id.subscribeRadioBtn) @@ -520,7 +576,12 @@ class WildcardFragment : Fragment() { if (eventPath.isNotEmpty() && eventMinEd.text.isNotBlank()) { eventMin = eventMinEd.text.toString().toULong().toLong() } - read(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin) + if (addressUpdateFragment.isICDDevice()) { + readICDConfig = + ReadICDConfig(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin) + } else { + read(isFabricFilteredEd.selectedItem.toString().toBoolean(), eventMin) + } requireActivity().runOnUiThread { dialog.dismiss() } } } @@ -537,18 +598,23 @@ class WildcardFragment : Fragment() { dialogView.findViewById(R.id.timedRequestTimeoutEd).text.toString() val imTimeout = dialogView.findViewById(R.id.imTimeoutEd).text.toString() scope.launch { - write( + val timedRequestTimeoutInt = if (timedRequestTimeoutMs.isEmpty()) { 0 } else { timedRequestTimeoutMs.toInt() - }, + } + val imTimeoutInt = if (imTimeout.isEmpty()) { 0 } else { imTimeout.toInt() } - ) + if (addressUpdateFragment.isICDDevice()) { + writeICDConfig = WriteInvokeICDConfig(timedRequestTimeoutInt, imTimeoutInt) + } else { + write(timedRequestTimeoutInt, imTimeoutInt) + } requireActivity().runOnUiThread { dialog.dismiss() } } } @@ -588,13 +654,24 @@ class WildcardFragment : Fragment() { if (eventPath.isNotEmpty() && eventMinEd.text.isNotBlank()) { eventMin = eventMinEd.text.toString().toULong().toLong() } - subscribe( - minIntervalEd.text.toString().toInt(), - maxIntervalEd.text.toString().toInt(), - keepSubscriptionsSp.selectedItem.toString().toBoolean(), - isFabricFilteredSp.selectedItem.toString().toBoolean(), - eventMin, - ) + if (addressUpdateFragment.isICDDevice()) { + subscribeICDConfig = + SubscribeICDConfig( + minIntervalEd.text.toString().toInt(), + maxIntervalEd.text.toString().toInt(), + keepSubscriptionsSp.selectedItem.toString().toBoolean(), + isFabricFilteredSp.selectedItem.toString().toBoolean(), + eventMin + ) + } else { + subscribe( + minIntervalEd.text.toString().toInt(), + maxIntervalEd.text.toString().toInt(), + keepSubscriptionsSp.selectedItem.toString().toBoolean(), + isFabricFilteredSp.selectedItem.toString().toBoolean(), + eventMin + ) + } } else { Log.e(TAG, "minInterval or maxInterval is empty!") } @@ -614,18 +691,23 @@ class WildcardFragment : Fragment() { dialogView.findViewById(R.id.timedRequestTimeoutEd).text.toString() val imTimeout = dialogView.findViewById(R.id.imTimeoutEd).text.toString() scope.launch { - invoke( + val timedRequestTimeoutInt = if (timedRequestTimeoutMs.isEmpty()) { 0 } else { timedRequestTimeoutMs.toInt() - }, + } + val imTimeoutInt = if (imTimeout.isEmpty()) { 0 } else { imTimeout.toInt() } - ) + if (addressUpdateFragment.isICDDevice()) { + invokeICDConfig = WriteInvokeICDConfig(timedRequestTimeoutInt, imTimeoutInt) + } else { + invoke(timedRequestTimeoutInt, imTimeoutInt) + } requireActivity().runOnUiThread { dialog.dismiss() } } } diff --git a/kotlin-detect-config.yaml b/kotlin-detect-config.yaml index f039b94ee0deae..8470d1687dbe14 100644 --- a/kotlin-detect-config.yaml +++ b/kotlin-detect-config.yaml @@ -343,6 +343,7 @@ complexity: - "**/src/controller/java/tests/matter/tlv/TlvReaderTest.kt" LargeClass: excludes: + - "**/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt" - "**/src/controller/java/generated/java/**/*" - "**/src/controller/java/tests/matter/tlv/TlvReadWriteTest.kt" - "**/src/controller/java/tests/matter/jsontlv/JsonToTlvToJsonTest.kt" From cd85f36417a4958cd275a401f00db64d13d8ca5f Mon Sep 17 00:00:00 2001 From: Suhas Shankar <118879678+su-shanka@users.noreply.github.com> Date: Thu, 9 May 2024 18:32:56 +0530 Subject: [PATCH 21/39] [Dns-sd] Added Operational Discovery and made browse delegate common (#32750) * Added operational discovery support * Restyled by whitespace * Restyled by clang-format * Updates as per review feedback * Restyled by whitespace * Restyled by clang-format * Updates based on additional feedback * Restyled by whitespace * updates as per feedback from review --------- Co-authored-by: Restyled.io --- src/lib/dnssd/IncrementalResolve.cpp | 19 ++++++---- src/lib/dnssd/IncrementalResolve.h | 7 ++-- src/lib/dnssd/ResolverProxy.cpp | 7 ++++ src/lib/dnssd/ResolverProxy.h | 1 + src/lib/dnssd/Resolver_ImplMinimalMdns.cpp | 37 +++++++++++++++---- src/lib/dnssd/Types.h | 18 +++++++-- .../dnssd/tests/TestIncrementalResolve.cpp | 26 +++++++------ src/lib/shell/commands/Dns.cpp | 27 ++++++++++++-- 8 files changed, 105 insertions(+), 37 deletions(-) diff --git a/src/lib/dnssd/IncrementalResolve.cpp b/src/lib/dnssd/IncrementalResolve.cpp index f083f852d7402f..867b1a8dcddb6c 100644 --- a/src/lib/dnssd/IncrementalResolve.cpp +++ b/src/lib/dnssd/IncrementalResolve.cpp @@ -137,7 +137,8 @@ SerializedQNameIterator StoredServerName::Get() const return SerializedQNameIterator(BytesRange(mNameBuffer, mNameBuffer + sizeof(mNameBuffer)), mNameBuffer); } -CHIP_ERROR IncrementalResolver::InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const mdns::Minimal::SrvRecord & srv) +CHIP_ERROR IncrementalResolver::InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const uint64_t ttl, + const mdns::Minimal::SrvRecord & srv) { AutoInactiveResetter inactiveReset(*this); @@ -183,6 +184,7 @@ CHIP_ERROR IncrementalResolver::InitializeParsing(mdns::Minimal::SerializedQName { return err; } + mSpecificResolutionData.Get().hasZeroTTL = (ttl == 0); } LogFoundOperationalSrvRecord(mSpecificResolutionData.Get().peerId, mTargetHostName.Get()); @@ -304,7 +306,7 @@ CHIP_ERROR IncrementalResolver::OnTxtRecord(const ResourceData & data, BytesRang } } - if (IsActiveBrowseParse()) + if (IsActiveCommissionParse()) { TxtParser delegate(mSpecificResolutionData.Get()); if (!ParseTxtRecord(data.GetData(), &delegate)) @@ -343,14 +345,17 @@ CHIP_ERROR IncrementalResolver::OnIpAddress(Inet::InterfaceId interface, const I CHIP_ERROR IncrementalResolver::Take(DiscoveredNodeData & outputData) { - VerifyOrReturnError(IsActiveBrowseParse(), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(IsActiveCommissionParse(), CHIP_ERROR_INCORRECT_STATE); IPAddressSorter::Sort(mCommonResolutionData.ipAddress, mCommonResolutionData.numIPs, mCommonResolutionData.interfaceId); - outputData.Set(); - CommissionNodeData & nodeData = outputData.Get(); - nodeData = mSpecificResolutionData.Get(); - CommonResolutionData & resolutionData = nodeData; + // Set the DiscoveredNodeData with CommissionNodeData info specific to commissionable/commisssioner + // node available in mSpecificResolutionData. + outputData.Set(mSpecificResolutionData.Get()); + + // IncrementalResolver stored CommonResolutionData separately in mCommonResolutionData hence copy the + // CommonResolutionData info from mCommonResolutionData, to CommissionNodeData within DiscoveredNodeData + CommonResolutionData & resolutionData = outputData.Get(); resolutionData = mCommonResolutionData; ResetToInactive(); diff --git a/src/lib/dnssd/IncrementalResolve.h b/src/lib/dnssd/IncrementalResolve.h index 4a8bc0c5792ee3..319a080dfa377f 100644 --- a/src/lib/dnssd/IncrementalResolve.h +++ b/src/lib/dnssd/IncrementalResolve.h @@ -100,7 +100,7 @@ class IncrementalResolver /// method. bool IsActive() const { return mSpecificResolutionData.Valid(); } - bool IsActiveBrowseParse() const { return mSpecificResolutionData.Is(); } + bool IsActiveCommissionParse() const { return mSpecificResolutionData.Is(); } bool IsActiveOperationalParse() const { return mSpecificResolutionData.Is(); } ServiceNameType GetCurrentType() const { return mServiceNameType; } @@ -115,7 +115,8 @@ class IncrementalResolver /// interested on, after which TXT and A/AAAA are looked for. /// /// If this function returns with error, the object will be in an inactive state. - CHIP_ERROR InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const mdns::Minimal::SrvRecord & srv); + CHIP_ERROR InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const uint64_t ttl, + const mdns::Minimal::SrvRecord & srv); /// Notify that a new record is being processed. /// Will handle filtering and processing of data to determine if the entry is relevant for @@ -150,7 +151,7 @@ class IncrementalResolver /// Take the current value of the object and clear it once returned. /// - /// Object must be in `IsActiveBrowseParse()` for this to succeed. + /// Object must be in `IsActive()` for this to succeed. /// Data will be returned (and cleared) even if not yet complete based /// on `GetMissingRequiredInformation()`. This method takes as much data as /// it was parsed so far. diff --git a/src/lib/dnssd/ResolverProxy.cpp b/src/lib/dnssd/ResolverProxy.cpp index e43028ee54023d..2fbf5b13a468e7 100644 --- a/src/lib/dnssd/ResolverProxy.cpp +++ b/src/lib/dnssd/ResolverProxy.cpp @@ -55,6 +55,13 @@ CHIP_ERROR ResolverProxy::DiscoverCommissioners(DiscoveryFilter filter) return mResolver.StartDiscovery(DiscoveryType::kCommissionerNode, filter, *mContext); } +CHIP_ERROR ResolverProxy::DiscoverOperationalNodes(DiscoveryFilter filter) +{ + VerifyOrReturnError(mContext != nullptr, CHIP_ERROR_INCORRECT_STATE); + + return mResolver.StartDiscovery(DiscoveryType::kOperational, filter, *mContext); +} + CHIP_ERROR ResolverProxy::StopDiscovery() { VerifyOrReturnError(mContext != nullptr, CHIP_ERROR_INCORRECT_STATE); diff --git a/src/lib/dnssd/ResolverProxy.h b/src/lib/dnssd/ResolverProxy.h index 58617b0d0162d7..d1888c36c1512d 100644 --- a/src/lib/dnssd/ResolverProxy.h +++ b/src/lib/dnssd/ResolverProxy.h @@ -54,6 +54,7 @@ class ResolverProxy CHIP_ERROR DiscoverCommissionableNodes(DiscoveryFilter filter = DiscoveryFilter()); CHIP_ERROR DiscoverCommissioners(DiscoveryFilter filter = DiscoveryFilter()); + CHIP_ERROR DiscoverOperationalNodes(DiscoveryFilter filter = DiscoveryFilter()); CHIP_ERROR StopDiscovery(); private: diff --git a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp index 8e17ce26b4eed5..efcdececed8f7b 100644 --- a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp @@ -213,7 +213,7 @@ void PacketParser::ParseSRVResource(const ResourceData & data) continue; } - CHIP_ERROR err = resolver.InitializeParsing(data.GetName(), srv); + CHIP_ERROR err = resolver.InitializeParsing(data.GetName(), data.GetTtlSeconds(), srv); if (err != CHIP_NO_ERROR) { // Receiving records that we do not need to parse is normal: @@ -363,6 +363,7 @@ void MinMdnsResolver::AdvancePendingResolverStates() { if (!resolver->IsActive()) { + ChipLogError(Discovery, "resolver inactive, continue to next"); continue; } @@ -370,7 +371,7 @@ void MinMdnsResolver::AdvancePendingResolverStates() if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress)) { - if (resolver->IsActiveBrowseParse()) + if (resolver->IsActiveCommissionParse()) { // Browse wants IP addresses ScheduleIpAddressResolve(resolver->GetTargetHostName()); @@ -399,7 +400,7 @@ void MinMdnsResolver::AdvancePendingResolverStates() } // SUCCESS. Call the delegates - if (resolver->IsActiveBrowseParse()) + if (resolver->IsActiveCommissionParse()) { MATTER_TRACE_SCOPE("Active commissioning delegate call", "MinMdnsResolver"); DiscoveredNodeData nodeData; @@ -452,19 +453,39 @@ void MinMdnsResolver::AdvancePendingResolverStates() else if (resolver->IsActiveOperationalParse()) { MATTER_TRACE_SCOPE("Active operational delegate call", "MinMdnsResolver"); - ResolvedNodeData nodeData; + ResolvedNodeData nodeResolvedData; + CHIP_ERROR err = resolver->Take(nodeResolvedData); - CHIP_ERROR err = resolver->Take(nodeData); if (err != CHIP_NO_ERROR) { - ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format()); + ChipLogError(Discovery, "Failed to take NodeData - result: %" CHIP_ERROR_FORMAT, err.Format()); continue; } - mActiveResolves.Complete(nodeData.operationalData.peerId); + if (mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kOperational)) + { + if (mDiscoveryContext != nullptr) + { + DiscoveredNodeData nodeData; + OperationalNodeBrowseData opNodeData; + + opNodeData.peerId = nodeResolvedData.operationalData.peerId; + opNodeData.hasZeroTTL = nodeResolvedData.operationalData.hasZeroTTL; + nodeData.Set(opNodeData); + mDiscoveryContext->OnNodeDiscovered(nodeData); + } + else + { +#if CHIP_MINMDNS_HIGH_VERBOSITY + ChipLogError(Discovery, "No delegate to report operational node discovery"); +#endif + } + } + + mActiveResolves.Complete(nodeResolvedData.operationalData.peerId); if (mOperationalDelegate != nullptr) { - mOperationalDelegate->OnOperationalNodeResolved(nodeData); + mOperationalDelegate->OnOperationalNodeResolved(nodeResolvedData); } else { diff --git a/src/lib/dnssd/Types.h b/src/lib/dnssd/Types.h index c88dd0a9c73522..1b9b19c0ad1bcc 100644 --- a/src/lib/dnssd/Types.h +++ b/src/lib/dnssd/Types.h @@ -197,10 +197,21 @@ struct CommonResolutionData struct OperationalNodeData { PeerId peerId; - + bool hasZeroTTL; void Reset() { peerId = PeerId(); } }; +struct OperationalNodeBrowseData : public OperationalNodeData +{ + OperationalNodeBrowseData() { Reset(); }; + void LogDetail() const + { + ChipLogDetail(Discovery, "Discovered Operational node:\r\n"); + ChipLogDetail(Discovery, "\tNode Instance: " ChipLogFormatPeerId, ChipLogValuePeerId(peerId)); + ChipLogDetail(Discovery, "\thasZeroTTL: %s\r\n", hasZeroTTL ? "true" : "false"); + } +}; + inline constexpr size_t kMaxDeviceNameLen = 32; inline constexpr size_t kMaxRotatingIdLen = 50; inline constexpr size_t kMaxPairingInstructionLen = 128; @@ -297,12 +308,13 @@ struct ResolvedNodeData } }; -using DiscoveredNodeData = Variant; +using DiscoveredNodeData = Variant; -/// Callbacks for discovering nodes advertising non-operational status: +/// Callbacks for discovering nodes advertising both operational and non-operational status: /// - Commissioners /// - Nodes in commissioning modes over IP (e.g. ethernet devices, devices already /// connected to thread/wifi or devices with a commissioning window open) +/// - Operational nodes class DiscoverNodeDelegate { public: diff --git a/src/lib/dnssd/tests/TestIncrementalResolve.cpp b/src/lib/dnssd/tests/TestIncrementalResolve.cpp index 0b5f26abbcd405..053d0dd96856ee 100644 --- a/src/lib/dnssd/tests/TestIncrementalResolve.cpp +++ b/src/lib/dnssd/tests/TestIncrementalResolve.cpp @@ -20,6 +20,7 @@ #include +#include #include #include #include @@ -161,7 +162,7 @@ TEST(TestIncrementalResolve, TestCreation) IncrementalResolver resolver; EXPECT_FALSE(resolver.IsActive()); - EXPECT_FALSE(resolver.IsActiveBrowseParse()); + EXPECT_FALSE(resolver.IsActiveCommissionParse()); EXPECT_FALSE(resolver.IsActiveOperationalParse()); EXPECT_TRUE( resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kSrvInitialization)); @@ -177,10 +178,10 @@ TEST(TestIncrementalResolve, TestInactiveResetOnInitError) PreloadSrvRecord(srvRecord); // test host name is not a 'matter' name - EXPECT_NE(resolver.InitializeParsing(kTestHostName.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_NE(resolver.InitializeParsing(kTestHostName.Serialized(), 0, srvRecord), CHIP_NO_ERROR); EXPECT_FALSE(resolver.IsActive()); - EXPECT_FALSE(resolver.IsActiveBrowseParse()); + EXPECT_FALSE(resolver.IsActiveCommissionParse()); EXPECT_FALSE(resolver.IsActiveOperationalParse()); } @@ -193,10 +194,10 @@ TEST(TestIncrementalResolve, TestStartOperational) SrvRecord srvRecord; PreloadSrvRecord(srvRecord); - EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), 1, srvRecord), CHIP_NO_ERROR); EXPECT_TRUE(resolver.IsActive()); - EXPECT_FALSE(resolver.IsActiveBrowseParse()); + EXPECT_FALSE(resolver.IsActiveCommissionParse()); EXPECT_TRUE(resolver.IsActiveOperationalParse()); EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress)); EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized()); @@ -211,10 +212,10 @@ TEST(TestIncrementalResolve, TestStartCommissionable) SrvRecord srvRecord; PreloadSrvRecord(srvRecord); - EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), 0, srvRecord), CHIP_NO_ERROR); EXPECT_TRUE(resolver.IsActive()); - EXPECT_TRUE(resolver.IsActiveBrowseParse()); + EXPECT_TRUE(resolver.IsActiveCommissionParse()); EXPECT_FALSE(resolver.IsActiveOperationalParse()); EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress)); EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized()); @@ -229,10 +230,10 @@ TEST(TestIncrementalResolve, TestStartCommissioner) SrvRecord srvRecord; PreloadSrvRecord(srvRecord); - EXPECT_EQ(resolver.InitializeParsing(kTestCommissionerNode.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_EQ(resolver.InitializeParsing(kTestCommissionerNode.Serialized(), 0, srvRecord), CHIP_NO_ERROR); EXPECT_TRUE(resolver.IsActive()); - EXPECT_TRUE(resolver.IsActiveBrowseParse()); + EXPECT_TRUE(resolver.IsActiveCommissionParse()); EXPECT_FALSE(resolver.IsActiveOperationalParse()); EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress)); EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized()); @@ -247,7 +248,7 @@ TEST(TestIncrementalResolve, TestParseOperational) SrvRecord srvRecord; PreloadSrvRecord(srvRecord); - EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), 1, srvRecord), CHIP_NO_ERROR); // once initialized, parsing should be ready however no IP address is available EXPECT_TRUE(resolver.IsActiveOperationalParse()); @@ -304,6 +305,7 @@ TEST(TestIncrementalResolve, TestParseOperational) // validate data as it was passed in EXPECT_EQ(nodeData.operationalData.peerId, PeerId().SetCompressedFabricId(0x1234567898765432LL).SetNodeId(0xABCDEFEDCBAABCDELL)); + EXPECT_FALSE(nodeData.operationalData.hasZeroTTL); EXPECT_EQ(nodeData.resolutionData.numIPs, 1u); EXPECT_EQ(nodeData.resolutionData.port, 0x1234); EXPECT_FALSE(nodeData.resolutionData.supportsTcp); @@ -324,10 +326,10 @@ TEST(TestIncrementalResolve, TestParseCommissionable) SrvRecord srvRecord; PreloadSrvRecord(srvRecord); - EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), srvRecord), CHIP_NO_ERROR); + EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), 0, srvRecord), CHIP_NO_ERROR); // once initialized, parsing should be ready however no IP address is available - EXPECT_TRUE(resolver.IsActiveBrowseParse()); + EXPECT_TRUE(resolver.IsActiveCommissionParse()); EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress)); EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized()); diff --git a/src/lib/shell/commands/Dns.cpp b/src/lib/shell/commands/Dns.cpp index 7fac0186da912f..c6a93657ca7440 100644 --- a/src/lib/shell/commands/Dns.cpp +++ b/src/lib/shell/commands/Dns.cpp @@ -83,15 +83,23 @@ class DnsShellResolverDelegate : public Dnssd::DiscoverNodeDelegate, public Addr AddressResolve::NodeLookupHandle & Handle() { return mSelfHandle; } + void LogOperationalNodeDiscovered(const Dnssd::OperationalNodeBrowseData & nodeData) + { + streamer_printf(streamer_get(), "DNS browse operational succeeded: \r\n"); + streamer_printf(streamer_get(), " Node Instance: " ChipLogFormatPeerId, ChipLogValuePeerId(nodeData.peerId)); + streamer_printf(streamer_get(), " hasZeroTTL: %s\r\n", nodeData.hasZeroTTL ? "true" : "false"); + } + void OnNodeDiscovered(const Dnssd::DiscoveredNodeData & discNodeData) override { - if (!discNodeData.Is()) + if (discNodeData.Is()) { - streamer_printf(streamer_get(), "DNS browse failed - not commission type node \r\n"); + LogOperationalNodeDiscovered(discNodeData.Get()); return; } - Dnssd::CommissionNodeData nodeData = discNodeData.Get(); + const auto & nodeData = discNodeData.Get(); + if (!nodeData.IsValid()) { streamer_printf(streamer_get(), "DNS browse failed - not found valid services \r\n"); @@ -237,6 +245,16 @@ CHIP_ERROR BrowseCommissionerHandler(int argc, char ** argv) return sResolverProxy.DiscoverCommissioners(filter); } +CHIP_ERROR BrowseOperationalHandler(int argc, char ** argv) +{ + Dnssd::DiscoveryFilter filter; + VerifyOrReturnError(ParseSubType(argc, argv, filter), CHIP_ERROR_INVALID_ARGUMENT); + + streamer_printf(streamer_get(), "Browsing operational...\r\n"); + + return sResolverProxy.DiscoverOperationalNodes(filter); +} + CHIP_ERROR BrowseHandler(int argc, char ** argv) { if (argc == 0) @@ -271,13 +289,14 @@ void RegisterDnsCommands() "Browse Matter commissionable nodes. Usage: dns browse commissionable [subtype]" }, { &BrowseCommissionerHandler, "commissioner", "Browse Matter commissioner nodes. Usage: dns browse commissioner [subtype]" }, + { &BrowseOperationalHandler, "operational", "Browse Matter operational nodes. Usage: dns browse operational" }, }; static const shell_command_t sDnsSubCommands[] = { { &ResolveHandler, "resolve", "Resolve the DNS service. Usage: dns resolve (e.g. dns resolve 5544332211 1)" }, { &BrowseHandler, "browse", - "Browse DNS services published by Matter nodes. Usage: dns browse " }, + "Browse DNS services published by Matter nodes. Usage: dns browse " }, }; static const shell_command_t sDnsCommand = { &DnsHandler, "dns", "Dns client commands" }; From 307cffb9c1a382ebfbdb428c8424469f3b673ec2 Mon Sep 17 00:00:00 2001 From: feasel <120589145+feasel0@users.noreply.github.com> Date: Thu, 9 May 2024 10:36:01 -0400 Subject: [PATCH 22/39] Updated unit tests in src/transport/tests/ to use PW instead of NL. (#33249) * Refactored TestSecureSessionTable.cpp to use TestSecureSessionTable as the pw test context. * Updated test_components[_nl].txt to move TransportLayerTests * Fixed formatting * Fixing merge conflict in test components nl * Fixing merge conflict * Updated TestSessionManagerDispatch to use staticly allocated context instead of dynamically. Changed all tests to use XTestSuite instead of per-test SetUp/TearDown. * Made context a non-pointer which is created/destroyed implicitly when each test case is run. * Reordered includes to be consistent with the standard. --------- Co-authored-by: Andrei Litvin --- .../openiotsdk/unit-tests/test_components.txt | 3 +- .../unit-tests/test_components_nl.txt | 1 - src/transport/tests/BUILD.gn | 6 +- src/transport/tests/TestCryptoContext.cpp | 56 +- .../tests/TestGroupMessageCounter.cpp | 216 ++++---- src/transport/tests/TestPeerConnections.cpp | 91 ++-- .../tests/TestPeerMessageCounter.cpp | 177 +++---- src/transport/tests/TestSecureSession.cpp | 156 ++---- .../tests/TestSecureSessionTable.cpp | 154 ++---- src/transport/tests/TestSessionManager.cpp | 478 +++++++----------- .../tests/TestSessionManagerDispatch.cpp | 96 +--- 11 files changed, 519 insertions(+), 915 deletions(-) diff --git a/src/test_driver/openiotsdk/unit-tests/test_components.txt b/src/test_driver/openiotsdk/unit-tests/test_components.txt index db6d92b6b25c2b..a509669979de01 100644 --- a/src/test_driver/openiotsdk/unit-tests/test_components.txt +++ b/src/test_driver/openiotsdk/unit-tests/test_components.txt @@ -17,5 +17,4 @@ SetupPayloadTests SupportTests UserDirectedCommissioningTests SecureChannelTests -ICDServerTests -InetLayerTests +ICDServerTests \ No newline at end of file diff --git a/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt b/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt index e00ff912d1bbc5..941d4863204b16 100644 --- a/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt +++ b/src/test_driver/openiotsdk/unit-tests/test_components_nl.txt @@ -2,4 +2,3 @@ AppTests DataModelTests MessagingLayerTests SecureChannelTestsNL -TransportLayerTests diff --git a/src/transport/tests/BUILD.gn b/src/transport/tests/BUILD.gn index 8e3f9365d023c8..7c38cea5e7e8eb 100644 --- a/src/transport/tests/BUILD.gn +++ b/src/transport/tests/BUILD.gn @@ -14,7 +14,7 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") -import("//build_overrides/nlunit_test.gni") +import("//build_overrides/pigweed.gni") import("${chip_root}/build/chip/chip_test_suite.gni") @@ -31,7 +31,7 @@ source_set("helpers") { ] } -chip_test_suite_using_nltest("tests") { +chip_test_suite("tests") { output_name = "libTransportLayerTests" test_sources = [ @@ -59,10 +59,8 @@ chip_test_suite_using_nltest("tests") { "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/lib/support:testing", - "${chip_root}/src/lib/support:testing_nlunit", "${chip_root}/src/protocols", "${chip_root}/src/transport", "${chip_root}/src/transport/tests:helpers", - "${nlunit_test_root}:nlunit-test", ] } diff --git a/src/transport/tests/TestCryptoContext.cpp b/src/transport/tests/TestCryptoContext.cpp index 9bcf0d25c7cbbb..45c3f3e5eb441e 100644 --- a/src/transport/tests/TestCryptoContext.cpp +++ b/src/transport/tests/TestCryptoContext.cpp @@ -17,13 +17,12 @@ */ #include -#include + +#include #include #include #include -#include - #include using namespace chip; @@ -48,7 +47,14 @@ struct PrivacyNonceTestEntry thePrivacyNonceTestVector[] = { }, }; -void TestBuildPrivacyNonce(nlTestSuite * apSuite, void * apContext) +class TestGroupCryptoContext : public ::testing::Test +{ +public: + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } +}; + +TEST_F(TestGroupCryptoContext, TestBuildPrivacyNonce) { for (const auto & testVector : thePrivacyNonceTestVector) { @@ -60,47 +66,9 @@ void TestBuildPrivacyNonce(nlTestSuite * apSuite, void * apContext) mic.SetTag(nullptr, testVector.mic, MIC_LENGTH); - NL_TEST_ASSERT(apSuite, CHIP_NO_ERROR == chip::CryptoContext::BuildPrivacyNonce(privacyNonce, sessionId, mic)); - NL_TEST_ASSERT(apSuite, 0 == memcmp(privacyNonceView.data(), expectedPrivacyNonce.data(), NONCE_LENGTH)); + EXPECT_EQ(CHIP_NO_ERROR, chip::CryptoContext::BuildPrivacyNonce(privacyNonce, sessionId, mic)); + EXPECT_EQ(0, memcmp(privacyNonceView.data(), expectedPrivacyNonce.data(), NONCE_LENGTH)); } } -/** - * Test Suite. It lists all the test functions. - */ -const nlTest sTests[] = { NL_TEST_DEF("TestBuildPrivacyNonce", TestBuildPrivacyNonce), NL_TEST_SENTINEL() }; - -/** - * Set up the test suite. - */ -int Test_Setup(void * inContext) -{ - CHIP_ERROR error = chip::Platform::MemoryInit(); - VerifyOrReturnError(error == CHIP_NO_ERROR, FAILURE); - return SUCCESS; -} - -/** - * Tear down the test suite. - */ -int Test_Teardown(void * inContext) -{ - chip::Platform::MemoryShutdown(); - return SUCCESS; -} - } // namespace - -/** - * Main - */ -int TestGroupCryptoContext() -{ - nlTestSuite theSuite = { "TestGroupCryptoContext", &sTests[0], Test_Setup, Test_Teardown }; - - // Run test suite againt one context. - nlTestRunner(&theSuite, nullptr); - return nlTestRunnerStats(&theSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestGroupCryptoContext) diff --git a/src/transport/tests/TestGroupMessageCounter.cpp b/src/transport/tests/TestGroupMessageCounter.cpp index 8e3101e482bd70..72fe57754e8976 100644 --- a/src/transport/tests/TestGroupMessageCounter.cpp +++ b/src/transport/tests/TestGroupMessageCounter.cpp @@ -21,17 +21,14 @@ * This file implements unit tests for the SessionManager implementation. */ +#include +#include + #include #include -#include #include #include -#include -#include - -#include - namespace { using namespace chip; @@ -101,11 +98,11 @@ class TestGroupPeerTable : public chip::Transport::GroupPeerTable } }; -void AddPeerTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, AddPeerTest) { NodeId peerNodeId = 1234; FabricIndex fabricIndex = 1; - uint32_t i = 0; + int i = 0; CHIP_ERROR err = CHIP_NO_ERROR; chip::Transport::PeerMessageCounter * counter = nullptr; chip::Transport::GroupPeerTable mGroupPeerMsgCounter; @@ -117,7 +114,7 @@ void AddPeerTest(nlTestSuite * inSuite, void * inContext) } while (err != CHIP_ERROR_TOO_MANY_PEER_NODES); - NL_TEST_ASSERT(inSuite, i == CHIP_CONFIG_MAX_GROUP_DATA_PEERS + 1); + EXPECT_EQ(i, CHIP_CONFIG_MAX_GROUP_DATA_PEERS + 1); i = 1; do @@ -125,10 +122,10 @@ void AddPeerTest(nlTestSuite * inSuite, void * inContext) err = mGroupPeerMsgCounter.FindOrAddPeer(++fabricIndex, peerNodeId, false, counter); i++; } while (err != CHIP_ERROR_TOO_MANY_PEER_NODES); - NL_TEST_ASSERT(inSuite, i == CHIP_CONFIG_MAX_FABRICS + 1); + EXPECT_EQ(i, CHIP_CONFIG_MAX_FABRICS + 1); } -void RemovePeerTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, RemovePeerTest) { NodeId peerNodeId = 1234; FabricIndex fabricIndex = 1; @@ -147,7 +144,7 @@ void RemovePeerTest(nlTestSuite * inSuite, void * inContext) } // Verify that table is indeed full (for control Peer) err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_TOO_MANY_PEER_NODES); + EXPECT_EQ(err, CHIP_ERROR_TOO_MANY_PEER_NODES); // Clear all Peer fabricIndex = 1; @@ -157,39 +154,39 @@ void RemovePeerTest(nlTestSuite * inSuite, void * inContext) for (uint32_t peerId = 0; peerId < CHIP_CONFIG_MAX_GROUP_CONTROL_PEERS; peerId++) { err = mGroupPeerMsgCounter.RemovePeer(fabricIndex, peerNodeId++, true); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); } fabricIndex++; } // Try re-adding the previous peer without any error err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = mGroupPeerMsgCounter.FindOrAddPeer(104, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = mGroupPeerMsgCounter.FindOrAddPeer(105, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = mGroupPeerMsgCounter.FindOrAddPeer(106, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Fabric removal test err = mGroupPeerMsgCounter.FabricRemoved(123); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NOT_FOUND); + EXPECT_EQ(err, CHIP_ERROR_NOT_FOUND); err = mGroupPeerMsgCounter.FabricRemoved(99); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = mGroupPeerMsgCounter.FabricRemoved(99); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_NOT_FOUND); + EXPECT_EQ(err, CHIP_ERROR_NOT_FOUND); // Verify that the Fabric List was compacted. - NL_TEST_ASSERT(inSuite, 106 == mGroupPeerMsgCounter.GetFabricIndexAt(0)); + EXPECT_EQ(106, mGroupPeerMsgCounter.GetFabricIndexAt(0)); } -void PeerRetrievalTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, PeerRetrievalTest) { NodeId peerNodeId = 1234; FabricIndex fabricIndex = 1; @@ -199,120 +196,120 @@ void PeerRetrievalTest(nlTestSuite * inSuite, void * inContext) chip::Transport::GroupPeerTable mGroupPeerMsgCounter; err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter != nullptr); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_NE(counter, nullptr); err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter2); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter2 != nullptr); - NL_TEST_ASSERT(inSuite, counter2 != counter); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_NE(counter2, nullptr); + EXPECT_NE(counter2, counter); err = mGroupPeerMsgCounter.FindOrAddPeer(fabricIndex, peerNodeId, true, counter2); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter2 == counter); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(counter2, counter); } -void CounterCommitRolloverTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, CounterCommitRolloverTest) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Transport::PeerMessageCounter * counter = nullptr; chip::Transport::GroupPeerTable mGroupPeerMsgCounter; err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter != nullptr); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_NE(counter, nullptr); err = counter->VerifyOrTrustFirstGroup(UINT32_MAX); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(UINT32_MAX); err = counter->VerifyOrTrustFirstGroup(0); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(0); err = counter->VerifyOrTrustFirstGroup(1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(1); } -void CounterTrustFirstTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, CounterTrustFirstTest) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Transport::PeerMessageCounter * counter = nullptr; chip::Transport::GroupPeerTable mGroupPeerMsgCounter; err = mGroupPeerMsgCounter.FindOrAddPeer(99, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter != nullptr); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_NE(counter, nullptr); err = counter->VerifyOrTrustFirstGroup(5656); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(5656); err = counter->VerifyOrTrustFirstGroup(5756); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(5756); err = counter->VerifyOrTrustFirstGroup(4756); - NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR); + EXPECT_NE(err, CHIP_NO_ERROR); // test sequential reception err = counter->VerifyOrTrustFirstGroup(5757); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(5757); err = counter->VerifyOrTrustFirstGroup(5758); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(5758); err = counter->VerifyOrTrustFirstGroup(5756); - NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR); + EXPECT_NE(err, CHIP_NO_ERROR); // Test Roll over err = mGroupPeerMsgCounter.FindOrAddPeer(1, 99, true, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, counter != nullptr); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_NE(counter, nullptr); err = counter->VerifyOrTrustFirstGroup(UINT32_MAX - 6); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(UINT32_MAX - 6); err = counter->VerifyOrTrustFirstGroup(UINT32_MAX - 1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(UINT32_MAX - 1); err = counter->VerifyOrTrustFirstGroup(UINT32_MAX); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(0); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(1); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(2); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(3); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(4); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(5); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(6); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(7); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); } -void ReorderPeerRemovalTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, ReorderPeerRemovalTest) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Transport::PeerMessageCounter * counter = nullptr; @@ -322,7 +319,7 @@ void ReorderPeerRemovalTest(nlTestSuite * inSuite, void * inContext) err = mGroupPeerMsgCounter.FindOrAddPeer(1, 2, true, counter); err = mGroupPeerMsgCounter.RemovePeer(1, 1, true); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetNodeIdAt(0, 0, true) == 2); + EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(0, 0, true), 2u); // with other list err = mGroupPeerMsgCounter.FindOrAddPeer(2, 1, false, counter); @@ -336,19 +333,19 @@ void ReorderPeerRemovalTest(nlTestSuite * inSuite, void * inContext) err = mGroupPeerMsgCounter.FindOrAddPeer(2, 9, false, counter); err = mGroupPeerMsgCounter.RemovePeer(2, 7, false); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetNodeIdAt(1, 6, false) == 9); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 6, false), 9u); err = mGroupPeerMsgCounter.RemovePeer(2, 4, false); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetNodeIdAt(1, 3, false) == 8); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 3, false), 8u); err = mGroupPeerMsgCounter.RemovePeer(2, 1, false); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetNodeIdAt(1, 0, false) == 9); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetNodeIdAt(1, 0, false), 9u); } -void ReorderFabricRemovalTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, ReorderFabricRemovalTest) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Transport::PeerMessageCounter * counter = nullptr; @@ -357,49 +354,49 @@ void ReorderFabricRemovalTest(nlTestSuite * inSuite, void * inContext) for (uint8_t i = 0; i < CHIP_CONFIG_MAX_FABRICS; i++) { err = mGroupPeerMsgCounter.FindOrAddPeer(static_cast(i + 1), 1, false, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); } // Try removing last Fabric first err = counter->VerifyOrTrustFirstGroup(1234); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(1234); err = mGroupPeerMsgCounter.FabricRemoved(CHIP_CONFIG_MAX_FABRICS); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetFabricIndexAt(CHIP_CONFIG_MAX_FABRICS - 1) == kUndefinedFabricIndex); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(CHIP_CONFIG_MAX_FABRICS - 1), kUndefinedFabricIndex); err = mGroupPeerMsgCounter.FindOrAddPeer(CHIP_CONFIG_MAX_FABRICS, 1, false, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Verify that the counter was indeed cleared err = counter->VerifyOrTrustFirstGroup(1234); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Set a counter that will be moved around err = counter->VerifyOrTrustFirstGroup(5656); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); counter->CommitGroup(5656); err = counter->VerifyOrTrustFirstGroup(4756); - NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR); + EXPECT_NE(err, CHIP_NO_ERROR); // Per Spec CHIP_CONFIG_MAX_FABRICS can only be as low as 4 err = mGroupPeerMsgCounter.RemovePeer(3, 1, false); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetFabricIndexAt(2) == CHIP_CONFIG_MAX_FABRICS); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(2), CHIP_CONFIG_MAX_FABRICS); err = mGroupPeerMsgCounter.RemovePeer(2, 1, false); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, mGroupPeerMsgCounter.GetFabricIndexAt(1) == CHIP_CONFIG_MAX_FABRICS - 1); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(mGroupPeerMsgCounter.GetFabricIndexAt(1), CHIP_CONFIG_MAX_FABRICS - 1); // Validate that counter value were moved around correctly err = mGroupPeerMsgCounter.FindOrAddPeer(CHIP_CONFIG_MAX_FABRICS, 1, false, counter); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = counter->VerifyOrTrustFirstGroup(4756); - NL_TEST_ASSERT(inSuite, err != CHIP_NO_ERROR); + EXPECT_NE(err, CHIP_NO_ERROR); } -void GroupMessageCounterTest(nlTestSuite * inSuite, void * inContext) +TEST(TestGroupMessageCounter, GroupMessageCounterTest) { chip::TestPersistentStorageDelegate delegate; @@ -407,7 +404,7 @@ void GroupMessageCounterTest(nlTestSuite * inSuite, void * inContext) uint32_t controlCounter = 0, dataCounter = 0; CHIP_ERROR err = groupCientCounter.Init(&delegate); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Start Test with Control counter // Counter should be random @@ -415,78 +412,45 @@ void GroupMessageCounterTest(nlTestSuite * inSuite, void * inContext) dataCounter = groupCientCounter.GetCounter(false); groupCientCounter.IncrementCounter(true); - NL_TEST_ASSERT(inSuite, (groupCientCounter.GetCounter(true) - controlCounter) == 1); + EXPECT_EQ((groupCientCounter.GetCounter(true) - controlCounter), 1u); groupCientCounter.SetCounter(true, UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); - NL_TEST_ASSERT(inSuite, groupCientCounter.GetCounter(true) == UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); + EXPECT_EQ(groupCientCounter.GetCounter(true), UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); // Test Persistence TestGroupOutgoingCounters groupCientCounter2(&delegate); - NL_TEST_ASSERT(inSuite, groupCientCounter2.GetCounter(true) == UINT32_MAX); - NL_TEST_ASSERT(inSuite, (groupCientCounter2.GetCounter(false) - dataCounter) == GROUP_MSG_COUNTER_MIN_INCREMENT); + EXPECT_EQ(groupCientCounter2.GetCounter(true), UINT32_MAX); + EXPECT_EQ((groupCientCounter2.GetCounter(false) - dataCounter), (uint32_t) GROUP_MSG_COUNTER_MIN_INCREMENT); // Test Roll over groupCientCounter2.IncrementCounter(true); - NL_TEST_ASSERT(inSuite, groupCientCounter2.GetCounter(true) == 0); + EXPECT_EQ(groupCientCounter2.GetCounter(true), 0u); TestGroupOutgoingCounters groupCientCounter3(&delegate); - NL_TEST_ASSERT(inSuite, groupCientCounter3.GetCounter(true) == (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT)); + EXPECT_EQ(groupCientCounter3.GetCounter(true), (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT)); // Redo the test with the second counter // Start Test with Control counter dataCounter = groupCientCounter.GetCounter(false); groupCientCounter.IncrementCounter(false); - NL_TEST_ASSERT(inSuite, (groupCientCounter.GetCounter(false) - dataCounter) == 1); + EXPECT_EQ((groupCientCounter.GetCounter(false) - dataCounter), 1u); groupCientCounter.SetCounter(false, UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); - NL_TEST_ASSERT(inSuite, groupCientCounter.GetCounter(false) == UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); + EXPECT_EQ(groupCientCounter.GetCounter(false), UINT32_MAX - GROUP_MSG_COUNTER_MIN_INCREMENT); // Test Persistence TestGroupOutgoingCounters groupCientCounter4(&delegate); - NL_TEST_ASSERT(inSuite, groupCientCounter4.GetCounter(false) == UINT32_MAX); + EXPECT_EQ(groupCientCounter4.GetCounter(false), UINT32_MAX); // Test Roll over groupCientCounter4.IncrementCounter(false); - NL_TEST_ASSERT(inSuite, groupCientCounter4.GetCounter(false) == 0); + EXPECT_EQ(groupCientCounter4.GetCounter(false), 0u); TestGroupOutgoingCounters groupCientCounter5(&delegate); - NL_TEST_ASSERT(inSuite, groupCientCounter5.GetCounter(false) == (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT)); + EXPECT_EQ(groupCientCounter5.GetCounter(false), (UINT32_MAX + GROUP_MSG_COUNTER_MIN_INCREMENT)); } } // namespace - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = -{ - NL_TEST_DEF("Add Peer", AddPeerTest), - NL_TEST_DEF("Remove Peer", RemovePeerTest), - NL_TEST_DEF("Peer retrieval", PeerRetrievalTest), - NL_TEST_DEF("Counter Rollover", CounterCommitRolloverTest), - NL_TEST_DEF("Counter Trust first", CounterTrustFirstTest), - NL_TEST_DEF("Reorder Peer removal", ReorderPeerRemovalTest), - NL_TEST_DEF("Reorder Fabric Removal", ReorderFabricRemovalTest), - NL_TEST_DEF("Group Message Counter", GroupMessageCounterTest), - NL_TEST_SENTINEL() -}; -// clang-format on - -/** - * Main - */ -int TestGroupMessageCounter() -{ - // Run test suit against one context - - nlTestSuite theSuite = { "Transport-TestGroupMessageCounter", &sTests[0], nullptr, nullptr }; - nlTestRunner(&theSuite, nullptr); - - return (nlTestRunnerStats(&theSuite)); -} - -CHIP_REGISTER_TEST_SUITE(TestGroupMessageCounter); diff --git a/src/transport/tests/TestPeerConnections.cpp b/src/transport/tests/TestPeerConnections.cpp index f4ea8c40244919..9beb263f1d15c8 100644 --- a/src/transport/tests/TestPeerConnections.cpp +++ b/src/transport/tests/TestPeerConnections.cpp @@ -22,13 +22,13 @@ * the SecureSessionTable class within the transport layer * */ + +#include + #include #include -#include #include -#include - namespace { using namespace chip; @@ -56,7 +56,14 @@ const FabricIndex kFabricIndex = 8; const CATValues kPeer1CATs = { { 0xABCD0001, 0xABCE0100, 0xABCD0020 } }; const CATValues kPeer2CATs = { { 0xABCD0012, kUndefinedCAT, kUndefinedCAT } }; -void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext) +class TestPeerConnections : public ::testing::Test +{ +public: + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } +}; + +TEST_F(TestPeerConnections, TestBasicFunctionality) { SecureSessionTable connections; System::Clock::Internal::MockClock clock; @@ -69,27 +76,27 @@ void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext) // First node, peer session id 1, local session id 2 auto optionalSession = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, 2, kLocalNodeId, kCasePeer1NodeId, kPeer1CATs, 1, kFabricIndex, GetDefaultMRPConfig()); - NL_TEST_ASSERT(inSuite, optionalSession.HasValue()); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetSecureSessionType() == SecureSession::Type::kCASE); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetPeerNodeId() == kCasePeer1NodeId); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetLocalNodeId() == kLocalNodeId); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->GetPeer() == ScopedNodeId(kCasePeer1NodeId, kFabricIndex)); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->GetLocalScopedNodeId() == ScopedNodeId(kLocalNodeId, kFabricIndex)); + EXPECT_TRUE(optionalSession.HasValue()); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetSecureSessionType(), SecureSession::Type::kCASE); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetPeerNodeId(), kCasePeer1NodeId); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetLocalNodeId(), kLocalNodeId); + EXPECT_EQ(optionalSession.Value()->GetPeer(), ScopedNodeId(kCasePeer1NodeId, kFabricIndex)); + EXPECT_EQ(optionalSession.Value()->GetLocalScopedNodeId(), ScopedNodeId(kLocalNodeId, kFabricIndex)); peerCATs = optionalSession.Value()->AsSecureSession()->GetPeerCATs(); - NL_TEST_ASSERT(inSuite, memcmp(&peerCATs, &kPeer1CATs, sizeof(CATValues)) == 0); + EXPECT_EQ(memcmp(&peerCATs, &kPeer1CATs, sizeof(CATValues)), 0); // Second node, peer session id 3, local session id 4 optionalSession = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, 4, kLocalNodeId, kCasePeer2NodeId, kPeer2CATs, 3, kFabricIndex, GetDefaultMRPConfig()); - NL_TEST_ASSERT(inSuite, optionalSession.HasValue()); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetSecureSessionType() == SecureSession::Type::kCASE); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetPeerNodeId() == kCasePeer2NodeId); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetLocalNodeId() == kLocalNodeId); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->GetPeer() == ScopedNodeId(kCasePeer2NodeId, kFabricIndex)); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->GetLocalScopedNodeId() == ScopedNodeId(kLocalNodeId, kFabricIndex)); - NL_TEST_ASSERT(inSuite, optionalSession.Value()->AsSecureSession()->GetLastActivityTime() == 100_ms64); + EXPECT_TRUE(optionalSession.HasValue()); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetSecureSessionType(), SecureSession::Type::kCASE); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetPeerNodeId(), kCasePeer2NodeId); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetLocalNodeId(), kLocalNodeId); + EXPECT_EQ(optionalSession.Value()->GetPeer(), ScopedNodeId(kCasePeer2NodeId, kFabricIndex)); + EXPECT_EQ(optionalSession.Value()->GetLocalScopedNodeId(), ScopedNodeId(kLocalNodeId, kFabricIndex)); + EXPECT_EQ(optionalSession.Value()->AsSecureSession()->GetLastActivityTime(), 100_ms64); peerCATs = optionalSession.Value()->AsSecureSession()->GetPeerCATs(); - NL_TEST_ASSERT(inSuite, memcmp(&peerCATs, &kPeer2CATs, sizeof(CATValues)) == 0); + EXPECT_EQ(memcmp(&peerCATs, &kPeer2CATs, sizeof(CATValues)), 0); // // Fill up the session table. @@ -99,14 +106,14 @@ void TestBasicFunctionality(nlTestSuite * inSuite, void * inContext) sessions[i] = connections.CreateNewSecureSessionForTest( SecureSession::Type::kCASE, static_cast(static_cast(i) + 6u), kLocalNodeId, kCasePeer2NodeId, kPeer2CATs, 3, kFabricIndex, GetDefaultMRPConfig()); - NL_TEST_ASSERT(inSuite, sessions[i].HasValue()); + EXPECT_TRUE(sessions[i].HasValue()); } // #endif System::Clock::Internal::SetSystemClockForTesting(realClock); } -void TestFindByKeyId(nlTestSuite * inSuite, void * inContext) +TEST_F(TestPeerConnections, TestFindByKeyId) { SecureSessionTable connections; System::Clock::Internal::MockClock clock; @@ -116,18 +123,18 @@ void TestFindByKeyId(nlTestSuite * inSuite, void * inContext) // First node, peer session id 1, local session id 2 auto optionalSession = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, 2, kLocalNodeId, kCasePeer1NodeId, kPeer1CATs, 1, kFabricIndex, GetDefaultMRPConfig()); - NL_TEST_ASSERT(inSuite, optionalSession.HasValue()); + EXPECT_TRUE(optionalSession.HasValue()); - NL_TEST_ASSERT(inSuite, !connections.FindSecureSessionByLocalKey(1).HasValue()); - NL_TEST_ASSERT(inSuite, connections.FindSecureSessionByLocalKey(2).HasValue()); + EXPECT_FALSE(connections.FindSecureSessionByLocalKey(1).HasValue()); + EXPECT_TRUE(connections.FindSecureSessionByLocalKey(2).HasValue()); // Second node, peer session id 3, local session id 4 optionalSession = connections.CreateNewSecureSessionForTest(SecureSession::Type::kCASE, 4, kLocalNodeId, kCasePeer2NodeId, kPeer2CATs, 3, kFabricIndex, GetDefaultMRPConfig()); - NL_TEST_ASSERT(inSuite, optionalSession.HasValue()); + EXPECT_TRUE(optionalSession.HasValue()); - NL_TEST_ASSERT(inSuite, !connections.FindSecureSessionByLocalKey(3).HasValue()); - NL_TEST_ASSERT(inSuite, connections.FindSecureSessionByLocalKey(4).HasValue()); + EXPECT_FALSE(connections.FindSecureSessionByLocalKey(3).HasValue()); + EXPECT_TRUE(connections.FindSecureSessionByLocalKey(4).HasValue()); System::Clock::Internal::SetSystemClockForTesting(realClock); } @@ -139,34 +146,4 @@ struct ExpiredCallInfo PeerAddress lastCallPeerAddress = PeerAddress::Uninitialized(); }; -int Initialize(void * apSuite) -{ - VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE); - return SUCCESS; -} - -int Finalize(void * aContext) -{ - chip::Platform::MemoryShutdown(); - return SUCCESS; -} - } // namespace - -// clang-format off -static const nlTest sTests[] = -{ - NL_TEST_DEF("BasicFunctionality", TestBasicFunctionality), - NL_TEST_DEF("FindByKeyId", TestFindByKeyId), - NL_TEST_SENTINEL() -}; -// clang-format on - -int TestPeerConnectionsFn() -{ - nlTestSuite theSuite = { "Transport-SecureSessionTable", &sTests[0], Initialize, Finalize }; - nlTestRunner(&theSuite, nullptr); - return nlTestRunnerStats(&theSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestPeerConnectionsFn) diff --git a/src/transport/tests/TestPeerMessageCounter.cpp b/src/transport/tests/TestPeerMessageCounter.cpp index 2c10ce4c8e6a0a..75f296b1bcba21 100644 --- a/src/transport/tests/TestPeerMessageCounter.cpp +++ b/src/transport/tests/TestPeerMessageCounter.cpp @@ -21,38 +21,37 @@ * This file implements unit tests for the SessionManager implementation. */ -#include -#include -#include - #include -#include -#include #include +#include + +#include +#include + namespace { using namespace chip; static uint32_t counterValuesArray[] = { 0, 10, 0x7FFFFFFF, 0x80000000, 0x80000001, 0x80000002, 0xFFFFFFF0, 0xFFFFFFFF }; -void GroupRollOverTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, GroupRollOverTest) { for (auto n : counterValuesArray) { for (uint32_t k = 1; k <= 2 * CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n), CHIP_NO_ERROR); counter.CommitGroup(n); // 1. A counter value of N + k comes in, we detect it as valid and commit it. - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + k), CHIP_NO_ERROR); counter.CommitGroup(n + k); // 2. A counter value of N comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); // 3. A counter value between N - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE and // N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE (but not including @@ -60,47 +59,45 @@ void GroupRollOverTest(nlTestSuite * inSuite, void * inContext) for (uint32_t i = n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; i != (n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE); i++) { - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(i) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyOrTrustFirstGroup(i), CHIP_NO_ERROR); } // 4. A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE comes in, is treated as valid. if (k != CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) { - NL_TEST_ASSERT(inSuite, - counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } else { - NL_TEST_ASSERT(inSuite, - counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } } -void GroupBackTrackTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, GroupBackTrackTest) { for (auto n : counterValuesArray) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n), CHIP_NO_ERROR); counter.CommitGroup(n); // 1. Some set of values N - k come in, for 0 < k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE. // All of those should be considered valid and committed. for (uint32_t k = 1; k * k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n - (k * k)) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n - (k * k)), CHIP_NO_ERROR); counter.CommitGroup(n - (k * k)); } // 2. Counter value N + 3 comes in - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n + 3) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + 3), CHIP_NO_ERROR); counter.CommitGroup(n + 3); // 3. The same set of values N - k come in as in step (1) and are all considered duplicates/out of window. for (uint32_t k = 1; k * k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n - (k * k)) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyOrTrustFirstGroup(n - (k * k)), CHIP_NO_ERROR); } // 4. The values that were not in the set in step (a) (but are at least N + 3 - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) @@ -111,29 +108,29 @@ void GroupBackTrackTest(nlTestSuite * inSuite, void * inContext) { continue; } - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(k), CHIP_NO_ERROR); counter.CommitGroup(k); } } } -void GroupBigLeapTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, GroupBigLeapTest) { for (auto n : counterValuesArray) { for (uint32_t k = (static_cast(1 << 31) - 5); k <= (static_cast(1 << 31) - 1); k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n), CHIP_NO_ERROR); counter.CommitGroup(n); // 1. A counter value of N + k comes in, we detect it as valid and commit it. - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + k), CHIP_NO_ERROR); counter.CommitGroup(n + k); // 2. A counter value of N comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyOrTrustFirstGroup(n), CHIP_NO_ERROR); // 3. A counter value between N and N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE // (but not including N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) comes in, we treat it as duplicate. @@ -149,38 +146,37 @@ void GroupBigLeapTest(nlTestSuite * inSuite, void * inContext) testValues.push_back(static_cast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE - 1)); // Will be inside the valid window of counter + (2^31 -1) - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); for (auto it : testValues) { - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(it) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyOrTrustFirstGroup(it), CHIP_NO_ERROR); } // 4. A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE comes in, is treated as valid. - NL_TEST_ASSERT(inSuite, - counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } -void GroupOutOfWindow(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, GroupOutOfWindow) { for (auto n : counterValuesArray) { for (uint32_t k = (static_cast(1 << 31)); k <= (static_cast(1 << 31) + 2); k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n), CHIP_NO_ERROR); counter.CommitGroup(n); // 1. A counter value of N + k comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyOrTrustFirstGroup(n + k) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyOrTrustFirstGroup(n + k), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); } } } -void UnicastSmallStepTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnicastSmallStepTest) { for (auto n : counterValuesArray) { @@ -201,22 +197,22 @@ void UnicastSmallStepTest(nlTestSuite * inSuite, void * inContext) } // A counter value of N comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); // A counter value of N + k comes in, we detect it as valid only if it would not // overflow, and commit it. if (k > UINT32_MAX - n) { - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n + k) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); // The other tests make no sense if we did not commit N+k as the new max counter. continue; } - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k), CHIP_NO_ERROR); counter.CommitEncryptedUnicast(n + k); // A counter value of N comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); // A counter value between N - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE and // N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE (but not including @@ -229,7 +225,7 @@ void UnicastSmallStepTest(nlTestSuite * inSuite, void * inContext) (n + k >= CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) ? (n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) : 0; for (uint32_t i = outOfWindowStart; i < outOfWindowEnd; i++) { - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(i) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyEncryptedUnicast(i), CHIP_NO_ERROR); } // A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE (if that does not @@ -239,20 +235,18 @@ void UnicastSmallStepTest(nlTestSuite * inSuite, void * inContext) { if ((k != CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) && (n + k != CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE)) { - NL_TEST_ASSERT( - inSuite, counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } else { - NL_TEST_ASSERT( - inSuite, counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } } } -void UnicastLargeStepTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnicastLargeStepTest) { for (auto n : counterValuesArray) { @@ -276,16 +270,16 @@ void UnicastLargeStepTest(nlTestSuite * inSuite, void * inContext) // if it would not overflow, and commit it. if (k > UINT32_MAX - n) { - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n + k) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); // The other tests make no sense if we did not commit N+k as the new max counter. continue; } - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k), CHIP_NO_ERROR); counter.CommitEncryptedUnicast(n + k); // 2. A counter value of N comes in, we detect it as duplicate. - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(n) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyEncryptedUnicast(n), CHIP_NO_ERROR); // 3. A counter value between N and N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE // (but not including N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) comes in, we treat it as duplicate. @@ -303,81 +297,77 @@ void UnicastLargeStepTest(nlTestSuite * inSuite, void * inContext) // n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE will be smaller than the current allowed counter values. if (n >= CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) { - NL_TEST_ASSERT(inSuite, - counter.VerifyEncryptedUnicast(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyEncryptedUnicast(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } for (auto it : testValues) { - NL_TEST_ASSERT(inSuite, counter.VerifyEncryptedUnicast(it) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyEncryptedUnicast(it), CHIP_NO_ERROR); } // 4. A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE comes in, is treated as valid. - NL_TEST_ASSERT(inSuite, - counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyEncryptedUnicast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } -void UnencryptedRollOverTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnencryptedRollOverTest) { for (auto n : counterValuesArray) { for (uint32_t k = 1; k <= 2 * CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); counter.CommitUnencrypted(n); // 1. A counter value of N + k comes in, we detect it as valid and commit it. - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + k), CHIP_NO_ERROR); counter.CommitUnencrypted(n + k); // 2. A counter value of N comes in, we detect it as duplicate if // it's in the window. if (k <= CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) { - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED); } else { - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); // Don't commit here so we change our max counter value. } // 4. A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE comes in, is treated as valid. if (k != CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) { - NL_TEST_ASSERT(inSuite, - counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } else { - NL_TEST_ASSERT(inSuite, - counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } } -void UnencryptedBackTrackTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnencryptedBackTrackTest) { for (auto n : counterValuesArray) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); counter.CommitUnencrypted(n); // 1. Some set of values N - k come in, for 0 < k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE. // All of those should be considered valid and committed. for (uint32_t k = 1; k * k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n - (k * k)) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n - (k * k)), CHIP_NO_ERROR); counter.CommitUnencrypted(n - (k * k)); } // 2. Counter value N + 3 comes in - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n + 3) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + 3), CHIP_NO_ERROR); counter.CommitUnencrypted(n + 3); // 3. The same set of values N - k come in as in step (1) and are all considered duplicates. @@ -385,7 +375,7 @@ void UnencryptedBackTrackTest(nlTestSuite * inSuite, void * inContext) // are out of window, and 25 is the biggest k*k value we are dealing with. for (uint32_t k = 1; k * k < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE; k++) { - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n - (k * k)) != CHIP_NO_ERROR); + EXPECT_NE(counter.VerifyUnencrypted(n - (k * k)), CHIP_NO_ERROR); } // 4. The values that were not in the set in step (a) (but are at least N + 3 - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) @@ -396,30 +386,30 @@ void UnencryptedBackTrackTest(nlTestSuite * inSuite, void * inContext) { continue; } - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(k), CHIP_NO_ERROR); counter.CommitUnencrypted(k); } } } -void UnencryptedBigLeapTest(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnencryptedBigLeapTest) { for (auto n : counterValuesArray) { for (uint32_t k = (static_cast(1 << 31) - 5); k <= (static_cast(1 << 31) - 1); k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); counter.CommitUnencrypted(n); // 1. A counter value of N + k comes in, we detect it as valid and commit it. - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + k), CHIP_NO_ERROR); counter.CommitUnencrypted(n + k); // 2. A counter value of N comes in, we detect it as valid, since // it's out of window. - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); // Don't commit, though. // 3. A counter value between N and N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE @@ -437,70 +427,35 @@ void UnencryptedBigLeapTest(nlTestSuite * inSuite, void * inContext) testValues.push_back(static_cast(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE - 1)); // Will be inside the valid window of counter + (2^31 -1) - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); for (auto it : testValues) { - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(it) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(it), CHIP_NO_ERROR); } // 4. A counter value of N + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE comes in, is treated as valid. - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + k - CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE), CHIP_NO_ERROR); } } } -void UnencryptedOutOfWindow(nlTestSuite * inSuite, void * inContext) +TEST(TestPeerMessageCounter, UnencryptedOutOfWindow) { for (auto n : counterValuesArray) { for (uint32_t k = (static_cast(1 << 31)); k <= (static_cast(1 << 31) + 2); k++) { chip::Transport::PeerMessageCounter counter; - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n), CHIP_NO_ERROR); counter.CommitUnencrypted(n); // 1. A counter value of N + k comes in, we treat it as valid, since // it's out of window. - NL_TEST_ASSERT(inSuite, counter.VerifyUnencrypted(n + k) == CHIP_NO_ERROR); + EXPECT_EQ(counter.VerifyUnencrypted(n + k), CHIP_NO_ERROR); } } } } // namespace - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = -{ - NL_TEST_DEF("Group Roll over Test", GroupRollOverTest), - NL_TEST_DEF("Group Backtrack Test", GroupBackTrackTest), - NL_TEST_DEF("Group All value test", GroupBigLeapTest), - NL_TEST_DEF("Group Out of Window Test", GroupOutOfWindow), - NL_TEST_DEF("Unicast small step Test", UnicastSmallStepTest), - NL_TEST_DEF("Unicast large step Test", UnicastLargeStepTest), - NL_TEST_DEF("Unencrypted Roll over Test", UnencryptedRollOverTest), - NL_TEST_DEF("Unencrypted Backtrack Test", UnencryptedBackTrackTest), - NL_TEST_DEF("Unencrypted All value test", UnencryptedBigLeapTest), - NL_TEST_DEF("Unencrypted Out of Window Test", UnencryptedOutOfWindow), - NL_TEST_SENTINEL() -}; -// clang-format on - -/** - * Main - */ -int TestPeerMessageCounter() -{ - // Run test suit against one context - - nlTestSuite theSuite = { "Transport-TestPeerMessageCounter", &sTests[0], nullptr, nullptr }; - nlTestRunner(&theSuite, nullptr); - - return (nlTestRunnerStats(&theSuite)); -} - -CHIP_REGISTER_TEST_SUITE(TestPeerMessageCounter); diff --git a/src/transport/tests/TestSecureSession.cpp b/src/transport/tests/TestSecureSession.cpp index 023876c4f7f3c1..672ba04e8fd38c 100644 --- a/src/transport/tests/TestSecureSession.cpp +++ b/src/transport/tests/TestSecureSession.cpp @@ -22,53 +22,51 @@ */ #include -#include +#include + +#include #include #include #include -#include #include -#include - using namespace chip; using namespace Crypto; -void SecureChannelInitTest(nlTestSuite * inSuite, void * inContext) +TEST(TestSecureSession, SecureChannelInitTest) { Crypto::DefaultSessionKeystore sessionKeystore; CryptoContext channel; P256Keypair keypair; - NL_TEST_ASSERT(inSuite, keypair.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); P256Keypair keypair2; - NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); // Test the channel is successfully created with valid parameters - NL_TEST_ASSERT(inSuite, - channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); + EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kInitiator), + CHIP_NO_ERROR); // Test the channel cannot be reinitialized - NL_TEST_ASSERT(inSuite, - channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kInitiator) == CHIP_ERROR_INCORRECT_STATE); + EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan(), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kInitiator), + CHIP_ERROR_INCORRECT_STATE); // Test the channel can be initialized with valid salt const char * salt = "Test Salt"; CryptoContext channel2; - NL_TEST_ASSERT(inSuite, - channel2.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), - ByteSpan((const uint8_t *) salt, strlen(salt)), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); + EXPECT_EQ(channel2.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kInitiator), + CHIP_NO_ERROR); } -void SecureChannelEncryptTest(nlTestSuite * inSuite, void * inContext) +TEST(TestSecureSession, SecureChannelEncryptTest) { Crypto::DefaultSessionKeystore sessionKeystore; CryptoContext channel; @@ -78,41 +76,38 @@ void SecureChannelEncryptTest(nlTestSuite * inSuite, void * inContext) MessageAuthenticationCode mac; packetHeader.SetSessionId(1); - NL_TEST_ASSERT(inSuite, packetHeader.IsEncrypted() == true); - NL_TEST_ASSERT(inSuite, packetHeader.MICTagLength() == 16); + EXPECT_TRUE(packetHeader.IsEncrypted()); + EXPECT_EQ(packetHeader.MICTagLength(), 16); CryptoContext::NonceStorage nonce; CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0); P256Keypair keypair; - NL_TEST_ASSERT(inSuite, keypair.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); P256Keypair keypair2; - NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); // Test uninitialized channel - NL_TEST_ASSERT(inSuite, - channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac) == - CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); + EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac), + CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); const char * salt = "Test Salt"; - NL_TEST_ASSERT(inSuite, - channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), - ByteSpan((const uint8_t *) salt, strlen(salt)), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); + EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kInitiator), + CHIP_NO_ERROR); // Test initialized channel, but invalid arguments - NL_TEST_ASSERT(inSuite, channel.Encrypt(nullptr, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT( - inSuite, channel.Encrypt(plain_text, sizeof(plain_text), nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel.Encrypt(nullptr, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel.Encrypt(plain_text, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); // Valid arguments - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_NO_ERROR); + EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), output, nonce, packetHeader, mac), CHIP_NO_ERROR); } -void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) +TEST(TestSecureSession, SecureChannelDecryptTest) { Crypto::DefaultSessionKeystore sessionKeystore; CryptoContext channel; @@ -122,8 +117,8 @@ void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) MessageAuthenticationCode mac; packetHeader.SetSessionId(1); - NL_TEST_ASSERT(inSuite, packetHeader.IsEncrypted() == true); - NL_TEST_ASSERT(inSuite, packetHeader.MICTagLength() == 16); + EXPECT_TRUE(packetHeader.IsEncrypted()); + EXPECT_EQ(packetHeader.MICTagLength(), 16); CryptoContext::NonceStorage nonce; CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), 0); @@ -131,77 +126,34 @@ void SecureChannelDecryptTest(nlTestSuite * inSuite, void * inContext) const char * salt = "Test Salt"; P256Keypair keypair; - NL_TEST_ASSERT(inSuite, keypair.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); P256Keypair keypair2; - NL_TEST_ASSERT(inSuite, keypair2.Initialize(ECPKeyTarget::ECDH) == CHIP_NO_ERROR); + EXPECT_EQ(keypair2.Initialize(ECPKeyTarget::ECDH), CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, - channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), - ByteSpan((const uint8_t *) salt, strlen(salt)), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kInitiator) == CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, channel.Encrypt(plain_text, sizeof(plain_text), encrypted, nonce, packetHeader, mac) == CHIP_NO_ERROR); + EXPECT_EQ(channel.InitFromKeyPair(sessionKeystore, keypair, keypair2.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kInitiator), + CHIP_NO_ERROR); + EXPECT_EQ(channel.Encrypt(plain_text, sizeof(plain_text), encrypted, nonce, packetHeader, mac), CHIP_NO_ERROR); CryptoContext channel2; uint8_t output[128]; // Uninitialized channel - NL_TEST_ASSERT(inSuite, - channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac) == - CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); - NL_TEST_ASSERT(inSuite, - channel2.InitFromKeyPair(sessionKeystore, keypair2, keypair.Pubkey(), - ByteSpan((const uint8_t *) salt, strlen(salt)), - CryptoContext::SessionInfoType::kSessionEstablishment, - CryptoContext::SessionRole::kResponder) == CHIP_NO_ERROR); + EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac), + CHIP_ERROR_INVALID_USE_OF_SESSION_KEY); + EXPECT_EQ(channel2.InitFromKeyPair(sessionKeystore, keypair2, keypair.Pubkey(), ByteSpan((const uint8_t *) salt, strlen(salt)), + CryptoContext::SessionInfoType::kSessionEstablishment, + CryptoContext::SessionRole::kResponder), + CHIP_NO_ERROR); // Channel initialized, but invalid arguments to decrypt - NL_TEST_ASSERT(inSuite, channel2.Decrypt(nullptr, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, 0, nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT( - inSuite, channel2.Decrypt(encrypted, sizeof(encrypted), nullptr, nonce, packetHeader, mac) == CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel2.Decrypt(nullptr, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel2.Decrypt(encrypted, 0, nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); + EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(encrypted), nullptr, nonce, packetHeader, mac), CHIP_ERROR_INVALID_ARGUMENT); // Valid arguments - NL_TEST_ASSERT(inSuite, channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac) == CHIP_NO_ERROR); + EXPECT_EQ(channel2.Decrypt(encrypted, sizeof(plain_text), output, nonce, packetHeader, mac), CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, memcmp(plain_text, output, sizeof(plain_text)) == 0); + EXPECT_EQ(memcmp(plain_text, output, sizeof(plain_text)), 0); } - -// Test Suite - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -static const nlTest sTests[] = -{ - NL_TEST_DEF("Init", SecureChannelInitTest), - NL_TEST_DEF("Encrypt", SecureChannelEncryptTest), - NL_TEST_DEF("Decrypt", SecureChannelDecryptTest), - - NL_TEST_SENTINEL() -}; -// clang-format on - -// clang-format off -static nlTestSuite sSuite = -{ - "Test-CHIP-CryptoContext", - &sTests[0], - nullptr, - nullptr -}; -// clang-format on - -/** - * Main - */ -int TestSecureSession() -{ - // Run test suit against one context - nlTestRunner(&sSuite, nullptr); - - return (nlTestRunnerStats(&sSuite)); -} - -CHIP_REGISTER_TEST_SUITE(TestSecureSession) diff --git a/src/transport/tests/TestSecureSessionTable.cpp b/src/transport/tests/TestSecureSessionTable.cpp index 7dbbeba654117f..323558a0cecd24 100644 --- a/src/transport/tests/TestSecureSessionTable.cpp +++ b/src/transport/tests/TestSecureSessionTable.cpp @@ -21,31 +21,27 @@ * This file implements unit tests for the SessionManager implementation. */ +#include +#include + +#include + #include "system/SystemClock.h" #include #include -#include #include #include -#include -#include - -#include -#include - namespace chip { namespace Transport { -class TestSecureSessionTable +class TestSecureSessionTable : public ::testing::Test { public: - // - // This test specifically validates eviction of sessions in the session table - // with various scenarios based on the existing set of sessions in the table - // and a provided session eviction hint - // - static void ValidateSessionSorting(nlTestSuite * inSuite, void * inContext); + static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } + + void ValidateSessionSorting(); private: struct SessionParameters @@ -88,7 +84,6 @@ class TestSecureSessionTable // void CreateSessionTable(std::vector & sessionParams); - nlTestSuite * mTestSuite; Platform::UniquePtr mSessionTable; std::vector> mSessionList; }; @@ -97,8 +92,8 @@ void TestSecureSessionTable::AllocateSession(const ScopedNodeId & sessionEvictio std::vector & sessionParameters, uint16_t evictedSessionIndex) { auto session = mSessionTable->CreateNewSecureSession(SecureSession::Type::kCASE, sessionEvictionHint); - NL_TEST_ASSERT(mTestSuite, session.HasValue()); - NL_TEST_ASSERT(mTestSuite, mSessionList[evictedSessionIndex].get()->mSessionReleased == true); + EXPECT_TRUE(session.HasValue()); + EXPECT_TRUE(mSessionList[evictedSessionIndex].get()->mSessionReleased); } void TestSecureSessionTable::CreateSessionTable(std::vector & sessionParams) @@ -106,7 +101,7 @@ void TestSecureSessionTable::CreateSessionTable(std::vector & mSessionList.clear(); mSessionTable = Platform::MakeUnique(); - NL_TEST_ASSERT(mTestSuite, mSessionTable.get() != nullptr); + EXPECT_NE(mSessionTable.get(), nullptr); mSessionTable->Init(); mSessionTable->SetMaxSessionTableSize(static_cast(sessionParams.size())); @@ -114,7 +109,7 @@ void TestSecureSessionTable::CreateSessionTable(std::vector & for (unsigned int i = 0; i < sessionParams.size(); i++) { auto session = mSessionTable->CreateNewSecureSession(SecureSession::Type::kCASE, ScopedNodeId()); - NL_TEST_ASSERT(mTestSuite, session.HasValue()); + EXPECT_TRUE(session.HasValue()); session.Value()->AsSecureSession()->Activate( ScopedNodeId(1, sessionParams[i].mPeer.GetFabricIndex()), sessionParams[i].mPeer, CATValues(), static_cast(i), @@ -131,11 +126,8 @@ void TestSecureSessionTable::CreateSessionTable(std::vector & } } -void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void * inContext) +void TestSecureSessionTable::ValidateSessionSorting() { - Platform::UniquePtr & _this = *static_cast *>(inContext); - _this->mTestSuite = inSuite; - // // This validates basic eviction. The table is full of sessions from Fabric1 from the same // Node (2). Eviction should select the oldest session in the table (with timestamp 1) and evict that @@ -152,8 +144,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 2, kFabric1 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 4); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 4); } // @@ -174,8 +166,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 2, kFabric1 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(2, kFabric2), sessionParamList, 4); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(2, kFabric2), sessionParamList, 4); } // @@ -200,8 +192,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 1); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 1); } // @@ -226,8 +218,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 3); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 3); } // @@ -252,8 +244,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 4); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(2, kFabric1), sessionParamList, 4); } // @@ -275,8 +267,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 2); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 2); } // @@ -303,8 +295,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kDefunct }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 3); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 3); } // @@ -337,8 +329,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(3), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 3); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 3); } // @@ -363,8 +355,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 2); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 2); } // @@ -390,8 +382,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 0); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(3, kFabric1), sessionParamList, 0); } // @@ -412,8 +404,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(4, kFabric1), sessionParamList, 2); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(4, kFabric1), sessionParamList, 2); } // @@ -432,8 +424,8 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(4, kFabric3), sessionParamList, 4); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(4, kFabric3), sessionParamList, 4); } // @@ -454,67 +446,19 @@ void TestSecureSessionTable::ValidateSessionSorting(nlTestSuite * inSuite, void { { 4, kFabric2 }, System::Clock::Timestamp(2), SecureSession::State::kActive }, }; - _this->CreateSessionTable(sessionParamList); - _this->AllocateSession(ScopedNodeId(4, kFabric3), sessionParamList, 5); + CreateSessionTable(sessionParamList); + AllocateSession(ScopedNodeId(4, kFabric3), sessionParamList, 5); } } -Platform::UniquePtr gTestSecureSessionTable; - -} // namespace Transport -} // namespace chip - -// Test Suite - -namespace { - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = -{ - NL_TEST_DEF("Validate Session Sorting (Over Minima)", chip::Transport::TestSecureSessionTable::ValidateSessionSorting), - NL_TEST_SENTINEL() -}; -// clang-format on - -int Initialize(void * apSuite) -{ - VerifyOrReturnError(chip::Platform::MemoryInit() == CHIP_NO_ERROR, FAILURE); - chip::Transport::gTestSecureSessionTable = chip::Platform::MakeUnique(); - return SUCCESS; -} - -int Finalize(void * aContext) +TEST_F(TestSecureSessionTable, ValidateSessionSorting) { - chip::Transport::gTestSecureSessionTable.reset(); - chip::Platform::MemoryShutdown(); - return SUCCESS; + // This calls TestSecureSessionTable::ValidateSessionSorting instead of just doing the + // tests directly in here, since the tests reference `SecureSession::State`, which is + // private. Defining the function inside TestSecureSessionTable allows State to be + // accessible since SecureSession contains `friend class TestSecureSessionTable`. + ValidateSessionSorting(); } -// clang-format off -nlTestSuite sSuite = -{ - "TestSecureSessionTable", - &sTests[0], - Initialize, - Finalize -}; -// clang-format on - -} // namespace - -/** - * Main - */ -int SecureSessionTableTest() -{ - // Run test suit against one context - nlTestRunner(&sSuite, &chip::Transport::gTestSecureSessionTable); - - int r = (nlTestRunnerStats(&sSuite)); - return r; -} - -CHIP_REGISTER_TEST_SUITE(SecureSessionTableTest); +} // namespace Transport +} // namespace chip diff --git a/src/transport/tests/TestSessionManager.cpp b/src/transport/tests/TestSessionManager.cpp index 12dc46ae360cc6..c5384a7be40328 100644 --- a/src/transport/tests/TestSessionManager.cpp +++ b/src/transport/tests/TestSessionManager.cpp @@ -31,8 +31,6 @@ #include #include #include -#include -#include #include #include #include @@ -41,8 +39,7 @@ #include #include -#include -#include +#include #include @@ -106,51 +103,52 @@ class TestSessMgrCallback : public SessionMessageDelegate if (LargeMessageSent) { - int compare = memcmp(msgBuf->Start(), LARGE_PAYLOAD, data_len); - NL_TEST_ASSERT(mSuite, compare == 0); + EXPECT_EQ(0, memcmp(msgBuf->Start(), LARGE_PAYLOAD, data_len)); } else { - int compare = memcmp(msgBuf->Start(), PAYLOAD, data_len); - NL_TEST_ASSERT(mSuite, compare == 0); + EXPECT_EQ(0, memcmp(msgBuf->Start(), PAYLOAD, data_len)); } ReceiveHandlerCallCount++; } - nlTestSuite * mSuite = nullptr; int ReceiveHandlerCallCount = 0; bool LargeMessageSent = false; }; -void CheckSimpleInitTest(nlTestSuite * inSuite, void * inContext) +class TestSessionManager : public ::testing::Test { - TestContext & ctx = *reinterpret_cast(inContext); +protected: + void SetUp() { ASSERT_EQ(mContext.Init(), CHIP_NO_ERROR); } + void TearDown() { mContext.Shutdown(); } + TestContext mContext; +}; + +TEST_F(TestSessionManager, CheckSimpleInitTest) +{ FabricTableHolder fabricTableHolder; SessionManager sessionManager; secure_channel::MessageCounterManager gMessageCounterManager; chip::TestPersistentStorageDelegate deviceStorage; chip::Crypto::DefaultSessionKeystore sessionKeystore; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); } -void CheckMessageTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, CheckMessageTest) { - TestContext & ctx = *reinterpret_cast(inContext); - uint16_t payload_len = sizeof(PAYLOAD); TestSessMgrCallback callback; callback.LargeMessageSent = false; chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); IPAddress addr; IPAddress::FromString("::1", addr); @@ -165,13 +163,10 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); - - callback.mSuite = inSuite; + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); sessionManager.SetMessageDelegate(&callback); @@ -180,23 +175,23 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. callback.ReceiveHandlerCallCount = 0; @@ -211,55 +206,53 @@ void CheckMessageTest(nlTestSuite * inSuite, void * inContext) EncryptedPacketBufferHandle preparedMessage; err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); // Let's send the max sized message and make sure it is received chip::System::PacketBufferHandle large_buffer = chip::MessagePacketBuffer::NewWithData(LARGE_PAYLOAD, kMaxAppMessageLen); - NL_TEST_ASSERT(inSuite, !large_buffer.IsNull()); + EXPECT_FALSE(large_buffer.IsNull()); callback.LargeMessageSent = true; err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(large_buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); uint16_t large_payload_len = sizeof(LARGE_PAYLOAD); // Let's send bigger message than supported and make sure it fails to send chip::System::PacketBufferHandle extra_large_buffer = chip::MessagePacketBuffer::NewWithData(LARGE_PAYLOAD, large_payload_len); - NL_TEST_ASSERT(inSuite, !extra_large_buffer.IsNull()); + EXPECT_FALSE(extra_large_buffer.IsNull()); callback.LargeMessageSent = true; err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(extra_large_buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_MESSAGE_TOO_LONG); + EXPECT_EQ(err, CHIP_ERROR_MESSAGE_TOO_LONG); sessionManager.Shutdown(); } -void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SendEncryptedPacketTest) { - TestContext & ctx = *reinterpret_cast(inContext); - uint16_t payload_len = sizeof(PAYLOAD); TestSessMgrCallback callback; callback.LargeMessageSent = false; chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); IPAddress addr; IPAddress::FromString("::1", addr); @@ -274,13 +267,10 @@ void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); - - callback.mSuite = inSuite; + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); sessionManager.SetMessageDelegate(&callback); @@ -289,23 +279,23 @@ void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. callback.ReceiveHandlerCallCount = 0; @@ -322,38 +312,36 @@ void SendEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); // Reset receive side message counter, or duplicated message will be denied. Transport::SecureSession * session = bobToAliceSession.Get().Value()->AsSecureSession(); session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); sessionManager.Shutdown(); } -void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SendBadEncryptedPacketTest) { - TestContext & ctx = *reinterpret_cast(inContext); - uint16_t payload_len = sizeof(PAYLOAD); TestSessMgrCallback callback; callback.LargeMessageSent = false; chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); IPAddress addr; IPAddress::FromString("::1", addr); @@ -368,13 +356,10 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); - - callback.mSuite = inSuite; + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); sessionManager.SetMessageDelegate(&callback); @@ -383,23 +368,23 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Should be able to send a message to itself by just calling send. callback.ReceiveHandlerCallCount = 0; @@ -416,13 +401,13 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); /* -------------------------------------------------------------------------------------------*/ // Reset receive side message counter, or duplicated message will be denied. @@ -433,59 +418,57 @@ void SendBadEncryptedPacketTest(nlTestSuite * inSuite, void * inContext) // Change Message ID EncryptedPacketBufferHandle badMessageCounterMsg = preparedMessage.CloneData(); - NL_TEST_ASSERT(inSuite, badMessageCounterMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR); + EXPECT_EQ(badMessageCounterMsg.ExtractPacketHeader(packetHeader), CHIP_NO_ERROR); uint32_t messageCounter = packetHeader.GetMessageCounter(); packetHeader.SetMessageCounter(messageCounter + 1); - NL_TEST_ASSERT(inSuite, badMessageCounterMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR); + EXPECT_EQ(badMessageCounterMsg.InsertPacketHeader(packetHeader), CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), badMessageCounterMsg); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); /* -------------------------------------------------------------------------------------------*/ session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1); // Change Key ID EncryptedPacketBufferHandle badKeyIdMsg = preparedMessage.CloneData(); - NL_TEST_ASSERT(inSuite, badKeyIdMsg.ExtractPacketHeader(packetHeader) == CHIP_NO_ERROR); + EXPECT_EQ(badKeyIdMsg.ExtractPacketHeader(packetHeader), CHIP_NO_ERROR); // the secure channel is setup to use key ID 1, and 2. So let's use 3 here. packetHeader.SetSessionId(3); - NL_TEST_ASSERT(inSuite, badKeyIdMsg.InsertPacketHeader(packetHeader) == CHIP_NO_ERROR); + EXPECT_EQ(badKeyIdMsg.InsertPacketHeader(packetHeader), CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), badKeyIdMsg); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); /* -------------------------------------------------------------------------------------------*/ session->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(1); // Send the correct encrypted msg err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); sessionManager.Shutdown(); } -void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SendPacketWithOldCounterTest) { - TestContext & ctx = *reinterpret_cast(inContext); - uint16_t payload_len = sizeof(PAYLOAD); TestSessMgrCallback callback; callback.LargeMessageSent = false; chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); IPAddress addr; IPAddress::FromString("::1", addr); @@ -500,13 +483,10 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); - - callback.mSuite = inSuite; + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); sessionManager.SetMessageDelegate(&callback); @@ -515,23 +495,23 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); callback.ReceiveHandlerCallCount = 0; @@ -547,53 +527,51 @@ void SendPacketWithOldCounterTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); // Now advance our message counter by 5. EncryptedPacketBufferHandle newMessage; for (size_t i = 0; i < 5; ++i) { buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), newMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); } err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), newMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); // Now resend our original message. It should be rejected as a duplicate. err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); sessionManager.Shutdown(); } -void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SendPacketWithTooOldCounterTest) { - TestContext & ctx = *reinterpret_cast(inContext); - uint16_t payload_len = sizeof(PAYLOAD); TestSessMgrCallback callback; callback.LargeMessageSent = false; chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); IPAddress addr; IPAddress::FromString("::1", addr); @@ -608,13 +586,10 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); - callback.mSuite = inSuite; - + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); sessionManager.SetMessageDelegate(&callback); Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); @@ -622,23 +597,23 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); callback.ReceiveHandlerCallCount = 0; @@ -654,13 +629,13 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) payloadHeader.SetInitiator(true); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 1); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 1); // Now advance our message counter by at least // CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE + 2, so preparedMessage will be @@ -669,30 +644,30 @@ void SendPacketWithTooOldCounterTest(nlTestSuite * inSuite, void * inContext) for (size_t i = 0; i < CHIP_CONFIG_MESSAGE_COUNTER_WINDOW_SIZE + 2; ++i) { buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, payload_len); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), newMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); } err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), newMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); // Now resend our original message. It should be rejected as a duplicate. err = sessionManager.SendPreparedMessage(aliceToBobSession.Get().Value(), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); - ctx.DrainAndServiceIO(); - NL_TEST_ASSERT(inSuite, callback.ReceiveHandlerCallCount == 2); + mContext.DrainAndServiceIO(); + EXPECT_EQ(callback.ReceiveHandlerCallCount, 2); sessionManager.Shutdown(); } -static void RandomSessionIdAllocatorOffset(nlTestSuite * inSuite, SessionManager & sessionManager, int max) +static void RandomSessionIdAllocatorOffset(SessionManager & sessionManager, int max) { // Allocate + free a pseudo-random number of sessions to create a // pseudo-random offset in mNextSessionId. @@ -702,27 +677,24 @@ static void RandomSessionIdAllocatorOffset(nlTestSuite * inSuite, SessionManager auto handle = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handle.HasValue()); + EXPECT_TRUE(handle.HasValue()); handle.Value()->AsSecureSession()->MarkForEviction(); } } -void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SessionAllocationTest) { - TestContext & ctx = *reinterpret_cast(inContext); - FabricTableHolder fabricTableHolder; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); secure_channel::MessageCounterManager messageCounterManager; TestPersistentStorageDelegate deviceStorage1, deviceStorage2; chip::Crypto::DefaultSessionKeystore sessionKeystore; SessionManager sessionManager; - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage1, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &messageCounterManager, &deviceStorage1, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); // Allocate a session. uint16_t sessionId1; @@ -730,7 +702,7 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) auto handle = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handle.HasValue()); + EXPECT_TRUE(handle.HasValue()); SessionHolder session; session.GrabPairingSession(handle.Value()); sessionId1 = session->AsSecureSession()->GetLocalSessionId(); @@ -749,8 +721,8 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) break; } auto sessionId = handle.Value()->AsSecureSession()->GetLocalSessionId(); - NL_TEST_ASSERT(inSuite, sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535)); - NL_TEST_ASSERT(inSuite, sessionId != 0); + EXPECT_TRUE(sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535)); + EXPECT_NE(sessionId, 0); prevSessionId = sessionId; } @@ -758,17 +730,16 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) sessionManager.Shutdown(); sessionManager.~SessionManager(); new (&sessionManager) SessionManager(); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage2, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &messageCounterManager, &deviceStorage2, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); // Allocate a single session so we know what random id we are starting at. { auto handle = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handle.HasValue()); + EXPECT_TRUE(handle.HasValue()); prevSessionId = handle.Value()->AsSecureSession()->GetLocalSessionId(); handle.Value()->AsSecureSession()->MarkForEviction(); } @@ -781,10 +752,10 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) auto handle = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handle.HasValue()); + EXPECT_TRUE(handle.HasValue()); auto sessionId = handle.Value()->AsSecureSession()->GetLocalSessionId(); - NL_TEST_ASSERT(inSuite, sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535)); - NL_TEST_ASSERT(inSuite, sessionId != 0); + EXPECT_TRUE(sessionId - prevSessionId == 1 || (sessionId == 1 && prevSessionId == 65535)); + EXPECT_NE(sessionId, 0); prevSessionId = sessionId; handle.Value()->AsSecureSession()->MarkForEviction(); } @@ -804,15 +775,15 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) handles[h] = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handles[h].HasValue()); + EXPECT_TRUE(handles[h].HasValue()); sessionIds[h] = handles[h].Value()->AsSecureSession()->GetLocalSessionId(); - RandomSessionIdAllocatorOffset(inSuite, sessionManager, maxOffset); + RandomSessionIdAllocatorOffset(sessionManager, maxOffset); } // Verify that none collide each other. for (size_t h = 0; h < numHandles; ++h) { - NL_TEST_ASSERT(inSuite, sessionIds[h] != sessionIds[(h + 1) % numHandles]); + EXPECT_NE(sessionIds[h], sessionIds[(h + 1) % numHandles]); } // Allocate through the entire session ID space and verify that none of @@ -822,11 +793,11 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) auto handle = sessionManager.AllocateSession( Transport::SecureSession::Type::kPASE, ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex)); - NL_TEST_ASSERT(inSuite, handle.HasValue()); + EXPECT_TRUE(handle.HasValue()); auto potentialCollision = handle.Value()->AsSecureSession()->GetLocalSessionId(); for (uint16_t sessionId : sessionIds) { - NL_TEST_ASSERT(inSuite, potentialCollision != sessionId); + EXPECT_NE(potentialCollision, sessionId); } handle.Value()->AsSecureSession()->MarkForEviction(); } @@ -841,10 +812,8 @@ void SessionAllocationTest(nlTestSuite * inSuite, void * inContext) sessionManager.Shutdown(); } -void SessionCounterExhaustedTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SessionCounterExhaustedTest) { - TestContext & ctx = *reinterpret_cast(inContext); - IPAddress addr; IPAddress::FromString("::1", addr); CHIP_ERROR err = CHIP_NO_ERROR; @@ -858,34 +827,33 @@ void SessionCounterExhaustedTest(nlTestSuite * inSuite, void * inContext) FabricIndex aliceFabricIndex = kUndefinedFabricIndex; FabricIndex bobFabricIndex = kUndefinedFabricIndex; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA1CertAsset().mCert, GetNodeA1CertAsset().mKey, &aliceFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); err = fabricTable.AddNewFabricForTestIgnoringCollisions(GetRootACertAsset().mCert, GetIAA1CertAsset().mCert, GetNodeA2CertAsset().mCert, GetNodeA2CertAsset().mKey, &bobFabricIndex); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); SessionHolder aliceToBobSession; err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, 2, fabricTable.FindFabricWithIndex(bobFabricIndex)->GetNodeId(), 1, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder bobToAliceSession; err = sessionManager.InjectPaseSessionWithTestKey(bobToAliceSession, 1, fabricTable.FindFabricWithIndex(aliceFabricIndex)->GetNodeId(), 2, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // ==== Set counter value to max ==== LocalSessionMessageCounter & counter = static_cast( @@ -894,7 +862,7 @@ void SessionCounterExhaustedTest(nlTestSuite * inSuite, void * inContext) // ==== Build a valid message with max counter value ==== chip::System::PacketBufferHandle buffer = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD)); - NL_TEST_ASSERT(inSuite, !buffer.IsNull()); + EXPECT_FALSE(buffer.IsNull()); PayloadHeader payloadHeader; @@ -906,23 +874,21 @@ void SessionCounterExhaustedTest(nlTestSuite * inSuite, void * inContext) EncryptedPacketBufferHandle preparedMessage; err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer), preparedMessage); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // ==== Build another message which will fail becuase message counter is exhausted ==== chip::System::PacketBufferHandle buffer2 = chip::MessagePacketBuffer::NewWithData(PAYLOAD, sizeof(PAYLOAD)); - NL_TEST_ASSERT(inSuite, !buffer2.IsNull()); + EXPECT_FALSE(buffer2.IsNull()); EncryptedPacketBufferHandle preparedMessage2; err = sessionManager.PrepareMessage(aliceToBobSession.Get().Value(), payloadHeader, std::move(buffer2), preparedMessage2); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_MESSAGE_COUNTER_EXHAUSTED); + EXPECT_EQ(err, CHIP_ERROR_MESSAGE_COUNTER_EXHAUSTED); sessionManager.Shutdown(); } -static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, SessionShiftingTest) { - TestContext & ctx = *reinterpret_cast(inContext); - IPAddress addr; IPAddress::FromString("::1", addr); @@ -937,18 +903,17 @@ static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext) chip::Crypto::DefaultSessionKeystore sessionKeystore; SessionManager sessionManager; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &messageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); SessionHolder aliceToBobSession; CHIP_ERROR err = sessionManager.InjectCaseSessionWithTestKey(aliceToBobSession, 2, 1, aliceNodeId, bobNodeId, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); class StickySessionDelegate : public SessionDelegate { @@ -958,17 +923,17 @@ static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext) } delegate; SessionHolderWithDelegate stickyAliceToBobSession(aliceToBobSession.Get().Value(), delegate); - NL_TEST_ASSERT(inSuite, aliceToBobSession.Contains(stickyAliceToBobSession.Get().Value())); + EXPECT_TRUE(aliceToBobSession.Contains(stickyAliceToBobSession.Get().Value())); SessionHolder bobToAliceSession; err = sessionManager.InjectCaseSessionWithTestKey(bobToAliceSession, 1, 2, bobNodeId, aliceNodeId, bobFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); SessionHolder newAliceToBobSession; err = sessionManager.InjectCaseSessionWithTestKey(newAliceToBobSession, 3, 4, aliceNodeId, bobNodeId, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); // Here we got 3 sessions, and 4 holders: // 1. alice -> bob: aliceToBobSession, stickyAliceToBobSession @@ -979,8 +944,8 @@ static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext) SecureSession * session2 = bobToAliceSession->AsSecureSession(); SecureSession * session3 = newAliceToBobSession->AsSecureSession(); - NL_TEST_ASSERT(inSuite, session1 != session3); - NL_TEST_ASSERT(inSuite, stickyAliceToBobSession->AsSecureSession() == session1); + EXPECT_NE(session1, session3); + EXPECT_EQ(stickyAliceToBobSession->AsSecureSession(), session1); // Now shift the 1st session to the 3rd one, after shifting, holders should be: // 1. alice -> bob: stickyAliceToBobSession @@ -988,22 +953,20 @@ static void SessionShiftingTest(nlTestSuite * inSuite, void * inContext) // 3. alice -> bob: aliceToBobSession, newAliceToBobSession sessionManager.GetSecureSessions().NewerSessionAvailable(newAliceToBobSession.Get().Value()->AsSecureSession()); - NL_TEST_ASSERT(inSuite, aliceToBobSession); - NL_TEST_ASSERT(inSuite, stickyAliceToBobSession); - NL_TEST_ASSERT(inSuite, newAliceToBobSession); + EXPECT_TRUE(aliceToBobSession); + EXPECT_TRUE(stickyAliceToBobSession); + EXPECT_TRUE(newAliceToBobSession); - NL_TEST_ASSERT(inSuite, stickyAliceToBobSession->AsSecureSession() == session1); - NL_TEST_ASSERT(inSuite, bobToAliceSession->AsSecureSession() == session2); - NL_TEST_ASSERT(inSuite, aliceToBobSession->AsSecureSession() == session3); - NL_TEST_ASSERT(inSuite, newAliceToBobSession->AsSecureSession() == session3); + EXPECT_EQ(stickyAliceToBobSession->AsSecureSession(), session1); + EXPECT_EQ(bobToAliceSession->AsSecureSession(), session2); + EXPECT_EQ(aliceToBobSession->AsSecureSession(), session3); + EXPECT_EQ(newAliceToBobSession->AsSecureSession(), session3); sessionManager.Shutdown(); } -static void TestFindSecureSessionForNode(nlTestSuite * inSuite, void * inContext) +TEST_F(TestSessionManager, TestFindSecureSessionForNode) { - TestContext & ctx = *reinterpret_cast(inContext); - IPAddress addr; IPAddress::FromString("::1", addr); @@ -1017,24 +980,23 @@ static void TestFindSecureSessionForNode(nlTestSuite * inSuite, void * inContext chip::Crypto::DefaultSessionKeystore sessionKeystore; SessionManager sessionManager; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &messageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&mContext.GetSystemLayer(), &mContext.GetTransportMgr(), &messageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); Transport::PeerAddress peer(Transport::PeerAddress::UDP(addr, CHIP_PORT)); SessionHolder aliceToBobSession; CHIP_ERROR err = sessionManager.InjectCaseSessionWithTestKey(aliceToBobSession, 2, 1, aliceNodeId, bobNodeId, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); aliceToBobSession->AsSecureSession()->MarkActive(); SessionHolder newAliceToBobSession; err = sessionManager.InjectCaseSessionWithTestKey(newAliceToBobSession, 3, 4, aliceNodeId, bobNodeId, aliceFabricIndex, peer, CryptoContext::SessionRole::kInitiator); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); while (System::SystemClock().GetMonotonicTimestamp() <= aliceToBobSession->AsSecureSession()->GetLastActivityTime()) { @@ -1045,75 +1007,11 @@ static void TestFindSecureSessionForNode(nlTestSuite * inSuite, void * inContext auto foundSession = sessionManager.FindSecureSessionForNode(ScopedNodeId(bobNodeId, aliceFabricIndex), MakeOptional(SecureSession::Type::kCASE)); - NL_TEST_ASSERT(inSuite, foundSession.HasValue()); - NL_TEST_ASSERT(inSuite, newAliceToBobSession.Contains(foundSession.Value())); - NL_TEST_ASSERT(inSuite, !aliceToBobSession.Contains(foundSession.Value())); + EXPECT_TRUE(foundSession.HasValue()); + EXPECT_TRUE(newAliceToBobSession.Contains(foundSession.Value())); + EXPECT_FALSE(aliceToBobSession.Contains(foundSession.Value())); sessionManager.Shutdown(); } -// Test Suite - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = -{ - NL_TEST_DEF("Simple Init Test", CheckSimpleInitTest), - NL_TEST_DEF("Message Self Test", CheckMessageTest), - NL_TEST_DEF("Send Encrypted Packet Test", SendEncryptedPacketTest), - NL_TEST_DEF("Send Bad Encrypted Packet Test", SendBadEncryptedPacketTest), - NL_TEST_DEF("Old counter Test", SendPacketWithOldCounterTest), - NL_TEST_DEF("Too-old counter Test", SendPacketWithTooOldCounterTest), - NL_TEST_DEF("Session Allocation Test", SessionAllocationTest), - NL_TEST_DEF("Session Counter Exhausted Test", SessionCounterExhaustedTest), - NL_TEST_DEF("SessionShiftingTest", SessionShiftingTest), - NL_TEST_DEF("TestFindSecureSessionForNode", TestFindSecureSessionForNode), - - NL_TEST_SENTINEL() -}; -// clang-format on - -int Initialize(void * aContext); -int Finalize(void * aContext); - -// clang-format off -nlTestSuite sSuite = -{ - "Test-CHIP-SessionManager", - &sTests[0], - Initialize, - Finalize -}; -// clang-format on - -/** - * Initialize the test suite. - */ -int Initialize(void * aContext) -{ - CHIP_ERROR err = reinterpret_cast(aContext)->Init(); - return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE; -} - -/** - * Finalize the test suite. - */ -int Finalize(void * aContext) -{ - reinterpret_cast(aContext)->Shutdown(); - return SUCCESS; -} - } // namespace - -/** - * Main - */ -int TestSessionManager() -{ - return chip::ExecuteTestsWithContext(&sSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestSessionManager); diff --git a/src/transport/tests/TestSessionManagerDispatch.cpp b/src/transport/tests/TestSessionManagerDispatch.cpp index 9d351ab3cacdb2..f90cb0fa2b21ac 100644 --- a/src/transport/tests/TestSessionManagerDispatch.cpp +++ b/src/transport/tests/TestSessionManagerDispatch.cpp @@ -31,15 +31,12 @@ #include #include #include -#include -#include #include #include #include #include -#include -#include +#include #include @@ -472,13 +469,13 @@ class TestSessionManagerCallback : public SessionMessageDelegate MessageTestEntry & testEntry = theMessageTestVector[mTestVectorIndex]; ChipLogProgress(Test, "OnMessageReceived: sessionId=0x%04x", testEntry.sessionId); - NL_TEST_ASSERT(mSuite, header.GetSessionId() == testEntry.sessionId); + EXPECT_EQ(header.GetSessionId(), testEntry.sessionId); size_t dataLength = msgBuf->DataLength(); size_t expectLength = testEntry.payloadLength; - NL_TEST_ASSERT(mSuite, dataLength == expectLength); - NL_TEST_ASSERT(mSuite, memcmp(msgBuf->Start(), testEntry.payload, dataLength) == 0); + EXPECT_EQ(dataLength, expectLength); + EXPECT_EQ(memcmp(msgBuf->Start(), testEntry.payload, dataLength), 0); ChipLogProgress(Test, "::: TestSessionManagerDispatch[%d] PASS", mTestVectorIndex); } @@ -491,7 +488,6 @@ class TestSessionManagerCallback : public SessionMessageDelegate unsigned NumMessagesReceived() { return mReceivedCount; } - nlTestSuite * mSuite = nullptr; unsigned mTestVectorIndex = 0; unsigned mReceivedCount = 0; }; @@ -505,18 +501,17 @@ PeerAddress AddressFromString(const char * str) return PeerAddress::UDP(addr); } -void TestSessionManagerInit(nlTestSuite * inSuite, TestContext & ctx, SessionManager & sessionManager) +void TestSessionManagerInit(TestContext & ctx, SessionManager & sessionManager) { static FabricTableHolder fabricTableHolder; static secure_channel::MessageCounterManager gMessageCounterManager; static chip::TestPersistentStorageDelegate deviceStorage; static chip::Crypto::DefaultSessionKeystore sessionKeystore; - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == fabricTableHolder.Init()); - NL_TEST_ASSERT(inSuite, - CHIP_NO_ERROR == - sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, - &fabricTableHolder.GetFabricTable(), sessionKeystore)); + EXPECT_EQ(CHIP_NO_ERROR, fabricTableHolder.Init()); + EXPECT_EQ(CHIP_NO_ERROR, + sessionManager.Init(&ctx.GetSystemLayer(), &ctx.GetTransportMgr(), &gMessageCounterManager, &deviceStorage, + &fabricTableHolder.GetFabricTable(), sessionKeystore)); } // constexpr chip::FabricId kFabricId1 = 0x2906C908D115D362; @@ -552,15 +547,23 @@ CHIP_ERROR InjectGroupSessionWithTestKey(SessionHolder & sessionHolder, MessageT return CHIP_NO_ERROR; } -void TestSessionManagerDispatch(nlTestSuite * inSuite, void * inContext) +class TestSessionManagerDispatch : public ::testing::Test +{ +protected: + void SetUp() { ASSERT_EQ(mContext.Init(), CHIP_NO_ERROR); } + void TearDown() { mContext.Shutdown(); } + + TestContext mContext; +}; + +TEST_F(TestSessionManagerDispatch, TestSessionManagerDispatch) { CHIP_ERROR err = CHIP_NO_ERROR; - TestContext & ctx = *reinterpret_cast(inContext); SessionManager sessionManager; TestSessionManagerCallback callback; - TestSessionManagerInit(inSuite, ctx, sessionManager); + TestSessionManagerInit(mContext, sessionManager); sessionManager.SetMessageDelegate(&callback); IPAddress addr; @@ -570,7 +573,6 @@ void TestSessionManagerDispatch(nlTestSuite * inSuite, void * inContext) SessionHolder aliceToBobSession; SessionHolder testGroupSession; - callback.mSuite = inSuite; for (unsigned i = 0; i < theMessageTestVectorLength; i++) { MessageTestEntry & testEntry = theMessageTestVector[i]; @@ -585,10 +587,10 @@ void TestSessionManagerDispatch(nlTestSuite * inSuite, void * inContext) err = sessionManager.InjectPaseSessionWithTestKey(aliceToBobSession, testEntry.sessionId, testEntry.peerNodeId, testEntry.sessionId, kFabricIndex, peer, CryptoContext::SessionRole::kResponder); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InjectGroupSessionWithTestKey(testGroupSession, testEntry); - NL_TEST_ASSERT(inSuite, CHIP_NO_ERROR == err); + EXPECT_EQ(CHIP_NO_ERROR, err); const char * plain = testEntry.plain; const ByteSpan expectedPlain(reinterpret_cast(plain), testEntry.plainLength); @@ -598,7 +600,7 @@ void TestSessionManagerDispatch(nlTestSuite * inSuite, void * inContext) const PeerAddress peerAddress = AddressFromString(testEntry.peerAddr); sessionManager.OnMessageReceived(peerAddress, std::move(msg)); - NL_TEST_ASSERT(inSuite, callback.NumMessagesReceived() == testEntry.expectedMessageCount); + EXPECT_EQ(callback.NumMessagesReceived(), testEntry.expectedMessageCount); if ((testEntry.expectedMessageCount == 0) && (callback.NumMessagesReceived() == 0)) { @@ -609,56 +611,4 @@ void TestSessionManagerDispatch(nlTestSuite * inSuite, void * inContext) sessionManager.Shutdown(); } -// ============================================================================ -// Test Suite Instrumenation -// ============================================================================ - -/** - * Initialize the test suite. - */ -int Initialize(void * aContext) -{ - CHIP_ERROR err = reinterpret_cast(aContext)->Init(); - return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE; -} - -/** - * Finalize the test suite. - */ -int Finalize(void * aContext) -{ - reinterpret_cast(aContext)->Shutdown(); - return SUCCESS; -} - -/** - * Test Suite that lists all the test functions. - */ -// clang-format off -const nlTest sTests[] = -{ - NL_TEST_DEF("Test Session Manager Dispatch", TestSessionManagerDispatch), - - NL_TEST_SENTINEL() -}; - -nlTestSuite sSuite = -{ - "TestSessionManagerDispatch", - &sTests[0], - Initialize, - Finalize -}; -// clang-format on - } // namespace - -/** - * Main - */ -int TestSessionManagerDispatchSuite() -{ - return chip::ExecuteTestsWithContext(&sSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestSessionManagerDispatchSuite); From d653df1b9bb98d6a32d7cdb456d7e72f9f022b38 Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Thu, 9 May 2024 08:26:30 -0700 Subject: [PATCH 23/39] Darwin `ValveConfigurationAndControl` introduction (#33370) * Darwin: promote `ValveConfigurationAndControl` to Introduced (YAML step) * Darwin: promote `ValveConfigurationAndControl` to Introduced (codegen step) --- .../CHIP/templates/availability.yaml | 58 +++++++ .../CHIP/zap-generated/MTRBaseClusters.h | 148 +++++++++--------- .../CHIP/zap-generated/MTRClusterConstants.h | 42 ++--- .../CHIP/zap-generated/MTRClusters.h | 52 +++--- .../zap-generated/MTRCommandPayloadsObjc.h | 8 +- .../CHIP/zap-generated/MTRStructsObjc.h | 10 +- .../zap-generated/cluster/Commands.h | 100 ------------ 7 files changed, 188 insertions(+), 230 deletions(-) diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index e4c27029b43ea0..f98ebd4deaf41c 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -8531,6 +8531,7 @@ - PM25ConcentrationMeasurement - RadonConcentrationMeasurement - TotalVolatileOrganicCompoundsConcentrationMeasurement + - ValveConfigurationAndControl attributes: ActivatedCarbonFilterMonitoring: - Condition @@ -8805,6 +8806,23 @@ - AttributeList - FeatureMap - ClusterRevision + ValveConfigurationAndControl: + - OpenDuration + - DefaultOpenDuration + - AutoCloseTime + - RemainingDuration + - CurrentState + - TargetState + - CurrentLevel + - TargetLevel + - DefaultOpenLevel + - ValveFault + - LevelStep + - GeneratedCommandList + - AcceptedCommandList + - AttributeList + - FeatureMap + - ClusterRevision commands: BooleanStateConfiguration: - SuppressAlarm @@ -8817,6 +8835,9 @@ - ResetCondition SmokeCOAlarm: - SelfTestRequest + ValveConfigurationAndControl: + - Open + - Close command fields: BooleanStateConfiguration: SuppressAlarm: @@ -8828,6 +8849,10 @@ - direction - wrap - lowestOff + ValveConfigurationAndControl: + Open: + - openDuration + - targetLevel structs: ActivatedCarbonFilterMonitoring: - ReplacementProductStruct @@ -8930,6 +8955,9 @@ - InterconnectSmokeAlarm - InterconnectCOAlarm - AllClear + ValveConfigurationAndControl: + - ValveStateChanged + - ValveFault event fields: BooleanStateConfiguration: AlarmsStateChanged: @@ -8958,6 +8986,12 @@ - alarmSeverityLevel InterconnectCOAlarm: - alarmSeverityLevel + ValveConfigurationAndControl: + ValveStateChanged: + - valveState + - valveLevel + ValveFault: + - valveFault enums: ActivatedCarbonFilterMonitoring: - DegradationDirectionEnum @@ -9022,6 +9056,9 @@ - MeasurementUnitEnum - MeasurementMediumEnum - LevelValueEnum + ValveConfigurationAndControl: + - ValveStateEnum + - StatusCodeEnum enum values: ActivatedCarbonFilterMonitoring: DegradationDirectionEnum: @@ -9319,6 +9356,13 @@ - Medium - High - Critical + ValveConfigurationAndControl: + ValveStateEnum: + - Closed + - Open + - Transitioning + StatusCodeEnum: + - FailureDueToFault bitmaps: ActivatedCarbonFilterMonitoring: - Feature @@ -9356,6 +9400,9 @@ - Feature TotalVolatileOrganicCompoundsConcentrationMeasurement: - Feature + ValveConfigurationAndControl: + - Feature + - ValveFaultBitmap bitmap values: ActivatedCarbonFilterMonitoring: Feature: @@ -9485,6 +9532,17 @@ - CriticalLevel - PeakMeasurement - AverageMeasurement + ValveConfigurationAndControl: + Feature: + - TimeSync + - Level + ValveFaultBitmap: + - GeneralFault + - Blocked + - Leaking + - NotConnected + - ShortCircuit + - CurrentExceeded provisional: clusters: # Targeting Spring 2024 Matter release diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 9635e226e522cd..1f150ed10ed3f9 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -7087,7 +7087,7 @@ MTR_NEWLY_AVAILABLE * * This cluster is used to configure a valve. */ -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRBaseClusterValveConfigurationAndControl : MTRGenericBaseCluster /** @@ -7095,99 +7095,99 @@ MTR_PROVISIONALLY_AVAILABLE * * This command is used to set the valve to its open position. */ -- (void)openWithParams:(MTRValveConfigurationAndControlClusterOpenParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)openWithParams:(MTRValveConfigurationAndControlClusterOpenParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)openWithCompletion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; + MTR_NEWLY_AVAILABLE; /** * Command Close * * This command is used to set the valve to its closed position. */ -- (void)closeWithParams:(MTRValveConfigurationAndControlClusterCloseParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)closeWithParams:(MTRValveConfigurationAndControlClusterCloseParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)closeWithCompletion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; + MTR_NEWLY_AVAILABLE; -- (void)readAttributeOpenDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeOpenDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeOpenDurationWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeOpenDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeOpenDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeDefaultOpenDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenDurationWithValue:(NSNumber * _Nullable)value completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenDurationWithValue:(NSNumber * _Nullable)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeDefaultOpenDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenDurationWithValue:(NSNumber * _Nullable)value completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenDurationWithValue:(NSNumber * _Nullable)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeDefaultOpenDurationWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeDefaultOpenDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeDefaultOpenDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAutoCloseTimeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAutoCloseTimeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAutoCloseTimeWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAutoCloseTimeWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAutoCloseTimeWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeRemainingDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeRemainingDurationWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeRemainingDurationWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeRemainingDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeRemainingDurationWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeCurrentStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeCurrentStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeCurrentStateWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeCurrentStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeCurrentStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeTargetStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeTargetStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeTargetStateWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeTargetStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeTargetStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeCurrentLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeCurrentLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeCurrentLevelWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeCurrentLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeCurrentLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeTargetLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeTargetLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeTargetLevelWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeTargetLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeTargetLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeDefaultOpenLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenLevelWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenLevelWithValue:(NSNumber * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeDefaultOpenLevelWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenLevelWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenLevelWithValue:(NSNumber * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeDefaultOpenLevelWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeDefaultOpenLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeDefaultOpenLevelWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeValveFaultWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeValveFaultWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeValveFaultWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeValveFaultWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeValveFaultWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeLevelStepWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeLevelStepWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeLevelStepWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeLevelStepWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeLevelStepWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeGeneratedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAcceptedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAcceptedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAcceptedCommandListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)readAttributeEventListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeEventListWithParams:(MTRSubscribeParams *)params @@ -7195,23 +7195,23 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeEventListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeAttributeListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeAttributeListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeAttributeListWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeFeatureMapWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeFeatureMapWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeFeatureMapWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; -- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeClusterRevisionWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (void)subscribeAttributeClusterRevisionWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_NEWLY_AVAILABLE; ++ (void)readAttributeClusterRevisionWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -7226,7 +7226,7 @@ MTR_PROVISIONALLY_AVAILABLE */ - (instancetype _Nullable)initWithDevice:(MTRBaseDevice *)device endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE; @end @@ -17715,28 +17715,28 @@ typedef NS_OPTIONS(uint16_t, MTRBooleanStateConfigurationSensorFaultBitmap) { } MTR_NEWLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRValveConfigurationAndControlStatusCode) { - MTRValveConfigurationAndControlStatusCodeFailureDueToFault MTR_PROVISIONALLY_AVAILABLE = 0x02, -} MTR_PROVISIONALLY_AVAILABLE; + MTRValveConfigurationAndControlStatusCodeFailureDueToFault MTR_NEWLY_AVAILABLE = 0x02, +} MTR_NEWLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRValveConfigurationAndControlValveState) { - MTRValveConfigurationAndControlValveStateClosed MTR_PROVISIONALLY_AVAILABLE = 0x00, - MTRValveConfigurationAndControlValveStateOpen MTR_PROVISIONALLY_AVAILABLE = 0x01, - MTRValveConfigurationAndControlValveStateTransitioning MTR_PROVISIONALLY_AVAILABLE = 0x02, -} MTR_PROVISIONALLY_AVAILABLE; + MTRValveConfigurationAndControlValveStateClosed MTR_NEWLY_AVAILABLE = 0x00, + MTRValveConfigurationAndControlValveStateOpen MTR_NEWLY_AVAILABLE = 0x01, + MTRValveConfigurationAndControlValveStateTransitioning MTR_NEWLY_AVAILABLE = 0x02, +} MTR_NEWLY_AVAILABLE; typedef NS_OPTIONS(uint32_t, MTRValveConfigurationAndControlFeature) { - MTRValveConfigurationAndControlFeatureTimeSync MTR_PROVISIONALLY_AVAILABLE = 0x1, - MTRValveConfigurationAndControlFeatureLevel MTR_PROVISIONALLY_AVAILABLE = 0x2, -} MTR_PROVISIONALLY_AVAILABLE; + MTRValveConfigurationAndControlFeatureTimeSync MTR_NEWLY_AVAILABLE = 0x1, + MTRValveConfigurationAndControlFeatureLevel MTR_NEWLY_AVAILABLE = 0x2, +} MTR_NEWLY_AVAILABLE; typedef NS_OPTIONS(uint16_t, MTRValveConfigurationAndControlValveFaultBitmap) { - MTRValveConfigurationAndControlValveFaultBitmapGeneralFault MTR_PROVISIONALLY_AVAILABLE = 0x1, - MTRValveConfigurationAndControlValveFaultBitmapBlocked MTR_PROVISIONALLY_AVAILABLE = 0x2, - MTRValveConfigurationAndControlValveFaultBitmapLeaking MTR_PROVISIONALLY_AVAILABLE = 0x4, - MTRValveConfigurationAndControlValveFaultBitmapNotConnected MTR_PROVISIONALLY_AVAILABLE = 0x8, - MTRValveConfigurationAndControlValveFaultBitmapShortCircuit MTR_PROVISIONALLY_AVAILABLE = 0x10, - MTRValveConfigurationAndControlValveFaultBitmapCurrentExceeded MTR_PROVISIONALLY_AVAILABLE = 0x20, -} MTR_PROVISIONALLY_AVAILABLE; + MTRValveConfigurationAndControlValveFaultBitmapGeneralFault MTR_NEWLY_AVAILABLE = 0x1, + MTRValveConfigurationAndControlValveFaultBitmapBlocked MTR_NEWLY_AVAILABLE = 0x2, + MTRValveConfigurationAndControlValveFaultBitmapLeaking MTR_NEWLY_AVAILABLE = 0x4, + MTRValveConfigurationAndControlValveFaultBitmapNotConnected MTR_NEWLY_AVAILABLE = 0x8, + MTRValveConfigurationAndControlValveFaultBitmapShortCircuit MTR_NEWLY_AVAILABLE = 0x10, + MTRValveConfigurationAndControlValveFaultBitmapCurrentExceeded MTR_NEWLY_AVAILABLE = 0x20, +} MTR_NEWLY_AVAILABLE; typedef NS_ENUM(uint16_t, MTRElectricalPowerMeasurementMeasurementType) { MTRElectricalPowerMeasurementMeasurementTypeUnspecified MTR_NEWLY_AVAILABLE = 0x00, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 5dd4cabe0fef0e..28e0e3d3264a00 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -148,7 +148,7 @@ typedef NS_ENUM(uint32_t, MTRClusterIDType) { MTRClusterIDTypeHEPAFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000071, MTRClusterIDTypeActivatedCarbonFilterMonitoringID MTR_NEWLY_AVAILABLE = 0x00000072, MTRClusterIDTypeBooleanStateConfigurationID MTR_NEWLY_AVAILABLE = 0x00000080, - MTRClusterIDTypeValveConfigurationAndControlID MTR_PROVISIONALLY_AVAILABLE = 0x00000081, + MTRClusterIDTypeValveConfigurationAndControlID MTR_NEWLY_AVAILABLE = 0x00000081, MTRClusterIDTypeElectricalPowerMeasurementID MTR_NEWLY_AVAILABLE = 0x00000090, MTRClusterIDTypeElectricalEnergyMeasurementID MTR_NEWLY_AVAILABLE = 0x00000091, MTRClusterIDTypeDemandResponseLoadControlID MTR_PROVISIONALLY_AVAILABLE = 0x00000096, @@ -2561,23 +2561,23 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterBooleanStateConfigurationAttributeClusterRevisionID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, // Cluster ValveConfigurationAndControl attributes - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeOpenDurationID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeDefaultOpenDurationID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAutoCloseTimeID MTR_PROVISIONALLY_AVAILABLE = 0x00000002, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeRemainingDurationID MTR_PROVISIONALLY_AVAILABLE = 0x00000003, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeCurrentStateID MTR_PROVISIONALLY_AVAILABLE = 0x00000004, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeTargetStateID MTR_PROVISIONALLY_AVAILABLE = 0x00000005, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeCurrentLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000006, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeTargetLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeDefaultOpenLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000008, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeValveFaultID MTR_PROVISIONALLY_AVAILABLE = 0x00000009, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeLevelStepID MTR_PROVISIONALLY_AVAILABLE = 0x0000000A, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeOpenDurationID MTR_NEWLY_AVAILABLE = 0x00000000, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeDefaultOpenDurationID MTR_NEWLY_AVAILABLE = 0x00000001, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAutoCloseTimeID MTR_NEWLY_AVAILABLE = 0x00000002, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeRemainingDurationID MTR_NEWLY_AVAILABLE = 0x00000003, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeCurrentStateID MTR_NEWLY_AVAILABLE = 0x00000004, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeTargetStateID MTR_NEWLY_AVAILABLE = 0x00000005, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeCurrentLevelID MTR_NEWLY_AVAILABLE = 0x00000006, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeTargetLevelID MTR_NEWLY_AVAILABLE = 0x00000007, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeDefaultOpenLevelID MTR_NEWLY_AVAILABLE = 0x00000008, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeValveFaultID MTR_NEWLY_AVAILABLE = 0x00000009, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeLevelStepID MTR_NEWLY_AVAILABLE = 0x0000000A, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeGeneratedCommandListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAcceptedCommandListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAttributeListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeFeatureMapID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, - MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeClusterRevisionID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeAttributeListID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeFeatureMapID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeFeatureMapID, + MTRAttributeIDTypeClusterValveConfigurationAndControlAttributeClusterRevisionID MTR_NEWLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeClusterRevisionID, // Cluster ElectricalPowerMeasurement attributes MTRAttributeIDTypeClusterElectricalPowerMeasurementAttributePowerModeID MTR_NEWLY_AVAILABLE = 0x00000000, @@ -6270,8 +6270,8 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterBooleanStateConfigurationCommandEnableDisableAlarmID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster ValveConfigurationAndControl commands - MTRCommandIDTypeClusterValveConfigurationAndControlCommandOpenID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTRCommandIDTypeClusterValveConfigurationAndControlCommandCloseID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTRCommandIDTypeClusterValveConfigurationAndControlCommandOpenID MTR_NEWLY_AVAILABLE = 0x00000000, + MTRCommandIDTypeClusterValveConfigurationAndControlCommandCloseID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster DemandResponseLoadControl commands MTRCommandIDTypeClusterDemandResponseLoadControlCommandRegisterLoadControlProgramRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, @@ -7195,8 +7195,8 @@ typedef NS_ENUM(uint32_t, MTREventIDType) { MTREventIDTypeClusterBooleanStateConfigurationEventSensorFaultID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster ValveConfigurationAndControl events - MTREventIDTypeClusterValveConfigurationAndControlEventValveStateChangedID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, - MTREventIDTypeClusterValveConfigurationAndControlEventValveFaultID MTR_PROVISIONALLY_AVAILABLE = 0x00000001, + MTREventIDTypeClusterValveConfigurationAndControlEventValveStateChangedID MTR_NEWLY_AVAILABLE = 0x00000000, + MTREventIDTypeClusterValveConfigurationAndControlEventValveFaultID MTR_NEWLY_AVAILABLE = 0x00000001, // Cluster ElectricalPowerMeasurement events MTREventIDTypeClusterElectricalPowerMeasurementEventMeasurementPeriodRangesID MTR_NEWLY_AVAILABLE = 0x00000000, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index d6689c33b1766e..6b68be46750c6c 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -3363,53 +3363,53 @@ MTR_NEWLY_AVAILABLE * Cluster Valve Configuration and Control * This cluster is used to configure a valve. */ -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRClusterValveConfigurationAndControl : MTRGenericCluster -- (void)openWithParams:(MTRValveConfigurationAndControlClusterOpenParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)openWithParams:(MTRValveConfigurationAndControlClusterOpenParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)openWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; -- (void)closeWithParams:(MTRValveConfigurationAndControlClusterCloseParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; + MTR_NEWLY_AVAILABLE; +- (void)closeWithParams:(MTRValveConfigurationAndControlClusterCloseParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_NEWLY_AVAILABLE; - (void)closeWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion - MTR_PROVISIONALLY_AVAILABLE; + MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeOpenDurationWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeOpenDurationWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeDefaultOpenDurationWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenDurationWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenDurationWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeDefaultOpenDurationWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenDurationWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenDurationWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAutoCloseTimeWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAutoCloseTimeWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeRemainingDurationWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeRemainingDurationWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeCurrentStateWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeCurrentStateWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeTargetStateWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeTargetStateWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeCurrentLevelWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeCurrentLevelWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeTargetLevelWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeTargetLevelWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeDefaultOpenLevelWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeDefaultOpenLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeDefaultOpenLevelWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_NEWLY_AVAILABLE; +- (void)writeAttributeDefaultOpenLevelWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeValveFaultWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeValveFaultWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeLevelStepWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeLevelStepWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeEventListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeAttributeListWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeFeatureMapWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeClusterRevisionWithParams:(MTRReadParams * _Nullable)params MTR_NEWLY_AVAILABLE; - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -3424,7 +3424,7 @@ MTR_PROVISIONALLY_AVAILABLE */ - (instancetype _Nullable)initWithDevice:(MTRDevice *)device endpointID:(NSNumber *)endpointID - queue:(dispatch_queue_t)queue MTR_PROVISIONALLY_AVAILABLE; + queue:(dispatch_queue_t)queue MTR_NEWLY_AVAILABLE; @end diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index a1d6600c95ed09..0ce6b87f0839d3 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -5300,12 +5300,12 @@ MTR_NEWLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRValveConfigurationAndControlClusterOpenParams : NSObject -@property (nonatomic, copy) NSNumber * _Nullable openDuration MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable openDuration MTR_NEWLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable targetLevel MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable targetLevel MTR_NEWLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5332,7 +5332,7 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRValveConfigurationAndControlClusterCloseParams : NSObject /** * Controls whether the command is a timed command (using Timed Invoke). diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index a29154cd4b5d23..0eb544cff8b980 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -1060,15 +1060,15 @@ MTR_NEWLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull sensorFault MTR_NEWLY_AVAILABLE; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRValveConfigurationAndControlClusterValveStateChangedEvent : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull valveState MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nullable valveLevel MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull valveState MTR_NEWLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable valveLevel MTR_NEWLY_AVAILABLE; @end -MTR_PROVISIONALLY_AVAILABLE +MTR_NEWLY_AVAILABLE @interface MTRValveConfigurationAndControlClusterValveFaultEvent : NSObject -@property (nonatomic, copy) NSNumber * _Nonnull valveFault MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull valveFault MTR_NEWLY_AVAILABLE; @end MTR_NEWLY_AVAILABLE diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index a59a148293d29a..c3034217db9c05 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -74224,7 +74224,6 @@ class SubscribeAttributeBooleanStateConfigurationClusterRevision : public Subscr } }; -#if MTR_ENABLE_PROVISIONAL /*----------------------------------------------------------------------------*\ | Cluster ValveConfigurationAndControl | 0x0081 | |------------------------------------------------------------------------------| @@ -74256,7 +74255,6 @@ class SubscribeAttributeBooleanStateConfigurationClusterRevision : public Subscr | * ValveFault | 0x0001 | \*----------------------------------------------------------------------------*/ -#if MTR_ENABLE_PROVISIONAL /* * Command Open */ @@ -74265,12 +74263,8 @@ class ValveConfigurationAndControlOpen : public ClusterCommand { ValveConfigurationAndControlOpen() : ClusterCommand("open") { -#if MTR_ENABLE_PROVISIONAL AddArgument("OpenDuration", 0, UINT32_MAX, &mRequest.openDuration); -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL AddArgument("TargetLevel", 0, UINT8_MAX, &mRequest.targetLevel); -#endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -74285,7 +74279,6 @@ class ValveConfigurationAndControlOpen : public ClusterCommand { __auto_type * cluster = [[MTRBaseClusterValveConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; __auto_type * params = [[MTRValveConfigurationAndControlClusterOpenParams alloc] init]; params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; -#if MTR_ENABLE_PROVISIONAL if (mRequest.openDuration.HasValue()) { if (mRequest.openDuration.Value().IsNull()) { params.openDuration = nil; @@ -74295,14 +74288,11 @@ class ValveConfigurationAndControlOpen : public ClusterCommand { } else { params.openDuration = nil; } -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL if (mRequest.targetLevel.HasValue()) { params.targetLevel = [NSNumber numberWithUnsignedChar:mRequest.targetLevel.Value()]; } else { params.targetLevel = nil; } -#endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; while (repeatCount--) { @@ -74326,8 +74316,6 @@ class ValveConfigurationAndControlOpen : public ClusterCommand { chip::app::Clusters::ValveConfigurationAndControl::Commands::Open::Type mRequest; }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL /* * Command Close */ @@ -74372,10 +74360,6 @@ class ValveConfigurationAndControlClose : public ClusterCommand { private: }; -#endif // MTR_ENABLE_PROVISIONAL - -#if MTR_ENABLE_PROVISIONAL - /* * Attribute OpenDuration */ @@ -74458,9 +74442,6 @@ class SubscribeAttributeValveConfigurationAndControlOpenDuration : public Subscr } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute DefaultOpenDuration */ @@ -74587,9 +74568,6 @@ class SubscribeAttributeValveConfigurationAndControlDefaultOpenDuration : public } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AutoCloseTime */ @@ -74672,9 +74650,6 @@ class SubscribeAttributeValveConfigurationAndControlAutoCloseTime : public Subsc } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute RemainingDuration */ @@ -74757,9 +74732,6 @@ class SubscribeAttributeValveConfigurationAndControlRemainingDuration : public S } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute CurrentState */ @@ -74842,9 +74814,6 @@ class SubscribeAttributeValveConfigurationAndControlCurrentState : public Subscr } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute TargetState */ @@ -74927,9 +74896,6 @@ class SubscribeAttributeValveConfigurationAndControlTargetState : public Subscri } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute CurrentLevel */ @@ -75012,9 +74978,6 @@ class SubscribeAttributeValveConfigurationAndControlCurrentLevel : public Subscr } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute TargetLevel */ @@ -75097,9 +75060,6 @@ class SubscribeAttributeValveConfigurationAndControlTargetLevel : public Subscri } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute DefaultOpenLevel */ @@ -75223,9 +75183,6 @@ class SubscribeAttributeValveConfigurationAndControlDefaultOpenLevel : public Su } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute ValveFault */ @@ -75308,9 +75265,6 @@ class SubscribeAttributeValveConfigurationAndControlValveFault : public Subscrib } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute LevelStep */ @@ -75393,9 +75347,6 @@ class SubscribeAttributeValveConfigurationAndControlLevelStep : public Subscribe } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute GeneratedCommandList */ @@ -75478,9 +75429,6 @@ class SubscribeAttributeValveConfigurationAndControlGeneratedCommandList : publi } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute AcceptedCommandList */ @@ -75563,7 +75511,6 @@ class SubscribeAttributeValveConfigurationAndControlAcceptedCommandList : public } }; -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL /* @@ -75649,7 +75596,6 @@ class SubscribeAttributeValveConfigurationAndControlEventList : public Subscribe }; #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL /* * Attribute AttributeList @@ -75733,9 +75679,6 @@ class SubscribeAttributeValveConfigurationAndControlAttributeList : public Subsc } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute FeatureMap */ @@ -75818,9 +75761,6 @@ class SubscribeAttributeValveConfigurationAndControlFeatureMap : public Subscrib } }; -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute ClusterRevision */ @@ -75903,8 +75843,6 @@ class SubscribeAttributeValveConfigurationAndControlClusterRevision : public Sub } }; -#endif // MTR_ENABLE_PROVISIONAL -#endif // MTR_ENABLE_PROVISIONAL /*----------------------------------------------------------------------------*\ | Cluster ElectricalPowerMeasurement | 0x0090 | |------------------------------------------------------------------------------| @@ -185404,98 +185342,60 @@ void registerClusterBooleanStateConfiguration(Commands & commands) } void registerClusterValveConfigurationAndControl(Commands & commands) { -#if MTR_ENABLE_PROVISIONAL using namespace chip::app::Clusters::ValveConfigurationAndControl; const char * clusterName = "ValveConfigurationAndControl"; commands_list clusterCommands = { make_unique(Id), // -#if MTR_ENABLE_PROVISIONAL make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // make_unique(Id), // -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // }; commands.RegisterCluster(clusterName, clusterCommands); -#endif // MTR_ENABLE_PROVISIONAL } void registerClusterElectricalPowerMeasurement(Commands & commands) { From d1d0d2bb4eaaa5fa19643f39c511bb80b6c296fd Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Thu, 9 May 2024 13:49:05 -0400 Subject: [PATCH 24/39] [Silbas] Remove AppConfig header from Silabs Platform (#33348) * remove app config header from the platform * replace SILABS_LOG with ChipLogProgress * Fix log --- .../silabs/DiagnosticDataProviderImpl.cpp | 1 - src/platform/silabs/PlatformManagerImpl.cpp | 2 - .../silabs/SiWx917/wifi/dhcp_client.cpp | 15 ++--- .../silabs/SiWx917/wifi/ethernetif.cpp | 38 ++++++----- .../silabs/SiWx917/wifi/lwip_netif.cpp | 1 - .../silabs/SiWx917/wifi/wfx_notify.cpp | 26 +++----- .../silabs/efr32/wifi/dhcp_client.cpp | 15 ++--- src/platform/silabs/efr32/wifi/ethernetif.cpp | 63 +++++++++---------- src/platform/silabs/efr32/wifi/lwip_netif.cpp | 2 +- src/platform/silabs/efr32/wifi/wfx_notify.cpp | 26 +++----- src/platform/silabs/rs911x/wfx_sl_ble_init.c | 1 - 11 files changed, 84 insertions(+), 106 deletions(-) diff --git a/src/platform/silabs/DiagnosticDataProviderImpl.cpp b/src/platform/silabs/DiagnosticDataProviderImpl.cpp index 02668206e26662..1dc408394f7a71 100644 --- a/src/platform/silabs/DiagnosticDataProviderImpl.cpp +++ b/src/platform/silabs/DiagnosticDataProviderImpl.cpp @@ -28,7 +28,6 @@ #if CHIP_DEVICE_CONFIG_ENABLE_THREAD #include #endif -#include "AppConfig.h" #include "FreeRTOS.h" #include "heap_4_silabs.h" #include diff --git a/src/platform/silabs/PlatformManagerImpl.cpp b/src/platform/silabs/PlatformManagerImpl.cpp index 669c9309d7ee57..7692ba922d2eaa 100644 --- a/src/platform/silabs/PlatformManagerImpl.cpp +++ b/src/platform/silabs/PlatformManagerImpl.cpp @@ -39,8 +39,6 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#include "AppConfig.h" - using namespace chip::DeviceLayer::Internal; namespace chip { diff --git a/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp index 9356586e5d6024..2ffc45d491ac66 100644 --- a/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp +++ b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp @@ -26,10 +26,11 @@ #include "wfx_host_events.h" #include "wifi_config.h" -#include "AppConfig.h" #include "FreeRTOS.h" #include "event_groups.h" +#include + #define MAX_DHCP_TRIES (4) #define NETIF_IPV4_ADDRESS(X, Y) (((X) >> (8 * Y)) & 0xFF) @@ -62,7 +63,7 @@ void dhcpclient_set_link_state(int link_up) if (link_up) { dhcp_state = DHCP_START; - SILABS_LOG("DHCP: Starting"); + ChipLogProgress(DeviceLayer, "DHCP: Starting"); } else { @@ -88,7 +89,7 @@ uint8_t dhcpclient_poll(void * arg) switch (dhcp_state) { case DHCP_START: - SILABS_LOG("DHCP: Wait addr"); + ChipLogProgress(DeviceLayer, "DHCP: Wait addr"); ip_addr_set_zero_ip4(&netif->ip_addr); ip_addr_set_zero_ip4(&netif->netmask); ip_addr_set_zero_ip4(&netif->gw); @@ -102,8 +103,8 @@ uint8_t dhcpclient_poll(void * arg) dhcp_state = DHCP_ADDRESS_ASSIGNED; uint64_t addr = netif->ip_addr.u_addr.ip4.addr; - SILABS_LOG("DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1), - NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3)); + ChipLogProgress(DeviceLayer, "DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1), + NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3)); } else { @@ -114,7 +115,7 @@ uint8_t dhcpclient_poll(void * arg) { dhcp_state = DHCP_TIMEOUT; - SILABS_LOG("*ERR*DHCP: Failed"); + ChipLogProgress(DeviceLayer, "*ERR*DHCP: Failed"); /* Stop DHCP */ dhcp_stop(netif); @@ -130,7 +131,7 @@ uint8_t dhcpclient_poll(void * arg) case DHCP_LINK_DOWN: /* Stop DHCP */ - SILABS_LOG("*ERR*DHCP Link down"); + ChipLogProgress(DeviceLayer, "*ERR*DHCP Link down"); dhcp_stop(netif); dhcp_state = DHCP_OFF; break; diff --git a/src/platform/silabs/SiWx917/wifi/ethernetif.cpp b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp index 0cc0061c6d9b81..8570fc4b9a4fb3 100644 --- a/src/platform/silabs/SiWx917/wifi/ethernetif.cpp +++ b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp @@ -45,6 +45,8 @@ extern "C" { #include "netif/etharp.h" #include "silabs_utils.h" +#include + StaticSemaphore_t xEthernetIfSemaBuffer; /***************************************************************************** @@ -130,13 +132,14 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) (memcmp(netif->hwaddr, dst_mac, netif->hwaddr_len) != 0)) { #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, + ChipLogProgress(DeviceLayer, "%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", + __func__, - dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], - b[12], b[13]); + b[12], b[13]); #endif return; } @@ -152,14 +155,15 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) bufferoffset += q->len; } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("%s: ACCEPT %d, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, - bufferoffset, + ChipLogProgress(DeviceLayer, + "%s: ACCEPT %d, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, + bufferoffset, - dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], - b[12], b[13]); + b[12], b[13]); #endif if (netif->input(p, netif) != ERR_OK) @@ -199,7 +203,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) uint16_t datalength = 0; #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("LWIP : low_level_output"); + ChipLogProgress(DeviceLayer, "LWIP : low_level_output"); #endif if (xSemaphoreTake(ethout_sem, portMAX_DELAY) != pdTRUE) { @@ -221,24 +225,24 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) VERIFY_STATUS_AND_RETURN(status); if (packet == NULL) { - SILABS_LOG("EN-RSI:No buf"); + ChipLogProgress(DeviceLayer, "EN-RSI:No buf"); xSemaphoreGive(ethout_sem); return SL_STATUS_ALLOCATION_FAILED; } memset(packet->desc, 0, sizeof(packet->desc)); #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("EN-RSI: Output"); + ChipLogProgress(DeviceLayer, "EN-RSI: Output"); #endif if ((netif->flags & (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) != (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) { - SILABS_LOG("EN-RSI:NOT UP"); + ChipLogProgress(DeviceLayer, "EN-RSI:NOT UP"); xSemaphoreGive(ethout_sem); return ERR_IF; } #ifdef WIFI_DEBUG_ENABLED uint8_t * b = (uint8_t *) p->payload; - SILABS_LOG("EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], b[1], b[2], b[3], - b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]); + ChipLogProgress(DeviceLayer, "EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], + b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]); #endif /* Generate the packet */ for (q = p, datalength = 0; q != NULL; q = q->next) @@ -252,13 +256,13 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) wfx_rsi_pkt_add_data(packet, (uint8_t *) (p->payload), LWIP_FRAME_ALIGNMENT - datalength, datalength); } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("EN-RSI: Sending %d", framelength); + ChipLogProgress(DeviceLayer, "EN-RSI: Sending %d", framelength); #endif packet->length = framelength & 0xFFF; packet->command = RSI_SEND_RAW_DATA; if (sl_si91x_driver_send_data_packet(SI91X_WLAN_CMD_QUEUE, buffer, 1000)) { - SILABS_LOG("*ERR*EN-RSI:Send fail"); + ChipLogProgress(DeviceLayer, "*ERR*EN-RSI:Send fail"); xSemaphoreGive(ethout_sem); return ERR_IF; } diff --git a/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp index a2610ef97f600d..d4bcbe4739a10f 100644 --- a/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp +++ b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp @@ -22,7 +22,6 @@ #include "wfx_host_events.h" #include "wifi_config.h" -#include "AppConfig.h" #include "dhcp_client.h" #include "ethernetif.h" diff --git a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp index 60ee45dee13e99..ded8e8389d256d 100644 --- a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp +++ b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp @@ -19,8 +19,6 @@ #include #include -#include "AppConfig.h" - #include "FreeRTOS.h" #include "event_groups.h" #include "silabs_utils.h" @@ -49,6 +47,8 @@ extern "C" { using namespace ::chip; using namespace ::chip::DeviceLayer; +#include + extern uint32_t retryInterval; /* * Notifications to the upper-layer @@ -67,8 +67,6 @@ void wfx_started_notify() sl_wfx_startup_ind_t evt; sl_wfx_mac_address_t mac; - SILABS_LOG("%s: started.", __func__); - memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_STARTUP_IND_ID; evt.header.length = sizeof evt; @@ -92,15 +90,13 @@ void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap) { sl_wfx_connect_ind_t evt; - SILABS_LOG("%s: started.", __func__); - if (status != SUCCESS_STATUS) { - SILABS_LOG("%s: error: failed status: %d.", __func__, status); + ChipLogProgress(DeviceLayer, "%s: error: failed status: %ld.", __func__, status); return; } - SILABS_LOG("%s: connected.", __func__); + ChipLogProgress(DeviceLayer, "%s: connected.", __func__); memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_CONNECT_IND_ID; @@ -125,8 +121,6 @@ void wfx_disconnected_notify(int32_t status) { sl_wfx_disconnect_ind_t evt; - SILABS_LOG("%s: started.", __func__); - memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_DISCONNECT_IND_ID; evt.header.length = sizeof evt; @@ -145,8 +139,6 @@ void wfx_ipv6_notify(int got_ip) { sl_wfx_generic_message_t eventData; - SILABS_LOG("%s: started.", __func__); - memset(&eventData, 0, sizeof(eventData)); eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP; eventData.header.length = sizeof(eventData.header); @@ -174,8 +166,6 @@ void wfx_ip_changed_notify(int got_ip) { sl_wfx_generic_message_t eventData; - SILABS_LOG("%s: started.", __func__); - memset(&eventData, 0, sizeof(eventData)); eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP; eventData.header.length = sizeof(eventData.header); @@ -208,7 +198,8 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry */ if (retryJoin < MAX_JOIN_RETRIES_COUNT) { - SILABS_LOG("wfx_retry_interval_handler : Next attempt after %d Seconds", CONVERT_MS_TO_SEC(WLAN_RETRY_TIMER_MS)); + ChipLogProgress(DeviceLayer, "wfx_retry_interval_handler : Next attempt after %d Seconds", + CONVERT_MS_TO_SEC(WLAN_RETRY_TIMER_MS)); #if SL_ICD_ENABLED // TODO: cleanup the retry logic MATTER-1921 if (!chip::Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen()) @@ -220,7 +211,7 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry } else { - SILABS_LOG("Connect failed after max %d tries", retryJoin); + ChipLogProgress(DeviceLayer, "Connect failed after max %d tries", retryJoin); } } else @@ -234,7 +225,8 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry { retryInterval = WLAN_MAX_RETRY_TIMER_MS; } - SILABS_LOG("wfx_retry_interval_handler : Next attempt after %d Seconds", CONVERT_MS_TO_SEC(retryInterval)); + ChipLogProgress(DeviceLayer, "wfx_retry_interval_handler : Next attempt after %ld Seconds", + CONVERT_MS_TO_SEC(retryInterval)); #if SL_ICD_ENABLED wfx_rsi_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); #endif // SL_ICD_ENABLED diff --git a/src/platform/silabs/efr32/wifi/dhcp_client.cpp b/src/platform/silabs/efr32/wifi/dhcp_client.cpp index 15c678515a0e62..c2a46d61dd6805 100644 --- a/src/platform/silabs/efr32/wifi/dhcp_client.cpp +++ b/src/platform/silabs/efr32/wifi/dhcp_client.cpp @@ -32,10 +32,11 @@ #include "wfx_host_events.h" #include "wifi_config.h" -#include "AppConfig.h" #include "FreeRTOS.h" #include "event_groups.h" +#include + #define MAX_DHCP_TRIES 4 #define NETIF_IPV4_ADDRESS(X, Y) (((X) >> (8 * Y)) & 0xFF) @@ -68,7 +69,7 @@ void dhcpclient_set_link_state(int link_up) if (link_up) { dhcp_state = DHCP_START; - SILABS_LOG("DHCP: Starting"); + ChipLogProgress(DeviceLayer, "DHCP: Starting"); } else { @@ -94,7 +95,7 @@ uint8_t dhcpclient_poll(void * arg) switch (dhcp_state) { case DHCP_START: - SILABS_LOG("DHCP: Wait addr"); + ChipLogProgress(DeviceLayer, "DHCP: Wait addr"); ip_addr_set_zero_ip4(&netif->ip_addr); ip_addr_set_zero_ip4(&netif->netmask); ip_addr_set_zero_ip4(&netif->gw); @@ -108,8 +109,8 @@ uint8_t dhcpclient_poll(void * arg) dhcp_state = DHCP_ADDRESS_ASSIGNED; uint64_t addr = netif->ip_addr.u_addr.ip4.addr; - SILABS_LOG("DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1), - NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3)); + ChipLogProgress(DeviceLayer, "DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1), + NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3)); } else { @@ -120,7 +121,7 @@ uint8_t dhcpclient_poll(void * arg) { dhcp_state = DHCP_TIMEOUT; - SILABS_LOG("*ERR*DHCP: Failed"); + ChipLogProgress(DeviceLayer, "*ERR*DHCP: Failed"); /* Stop DHCP */ dhcp_stop(netif); @@ -136,7 +137,7 @@ uint8_t dhcpclient_poll(void * arg) case DHCP_LINK_DOWN: /* Stop DHCP */ - SILABS_LOG("*ERR*DHCP Link down"); + ChipLogProgress(DeviceLayer, "*ERR*DHCP Link down"); dhcp_stop(netif); dhcp_state = DHCP_OFF; break; diff --git a/src/platform/silabs/efr32/wifi/ethernetif.cpp b/src/platform/silabs/efr32/wifi/ethernetif.cpp index 32d7ee1d079d0d..d07c14f61e2287 100644 --- a/src/platform/silabs/efr32/wifi/ethernetif.cpp +++ b/src/platform/silabs/efr32/wifi/ethernetif.cpp @@ -60,12 +60,7 @@ extern "C" { #include "lwip/timeouts.h" #include "netif/etharp.h" -#ifndef SILABS_LOG -extern "C" { -void silabsLog(const char * aFormat, ...); -#define SILABS_LOG(...) silabsLog(__VA_ARGS__); -} -#endif +#include StaticSemaphore_t xEthernetIfSemaBuffer; @@ -152,13 +147,14 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) (memcmp(netif->hwaddr, dst_mac, netif->hwaddr_len) != 0)) { #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, + ChipLogProgress(DeviceLayer, "%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", + __func__, - dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], - b[12], b[13]); + b[12], b[13]); #endif return; } @@ -174,27 +170,28 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) bufferoffset += q->len; } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("%s: ACCEPT %d, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, - bufferoffset, + ChipLogProgress(DeviceLayer, + "%s: ACCEPT %ld, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__, + bufferoffset, - dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], + dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], - src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], + src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5], - b[12], b[13]); + b[12], b[13]); #endif if (netif->input(p, netif) != ERR_OK) { gOverrunCount++; - SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount); + ChipLogProgress(DeviceLayer, "overrun count entering when fail to alloc value %ld", gOverrunCount); pbuf_free(p); } } else { gOverrunCount++; - SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount); + ChipLogProgress(DeviceLayer, "overrun count entering when fail to alloc value %ld", gOverrunCount); } } @@ -241,9 +238,9 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) // 12 is size of other data in buffer struct, user shouldn't have to care about this? if (sl_wfx_host_allocate_buffer((void **) &tx_buffer, SL_WFX_TX_FRAME_BUFFER, asize) != SL_STATUS_OK) { - SILABS_LOG("*ERR*EN-Out: No mem frame len=%d", framelength); + ChipLogProgress(DeviceLayer, "*ERR*EN-Out: No mem frame len=%ld", framelength); gOverrunCount++; - SILABS_LOG("overrun count exiting when faied to alloc value %d", gOverrunCount); + ChipLogProgress(DeviceLayer, "overrun count exiting when faied to alloc value %ld", gOverrunCount); return ERR_MEM; } buffer = tx_buffer->body.packet_data; @@ -265,7 +262,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) result = SL_STATUS_FAIL; #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("WF200: Out %d", (int) framelength); + ChipLogProgress(DeviceLayer, "WF200: Out %d", (int) framelength); #endif /* send the generated frame over Wifi network */ @@ -277,7 +274,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) if (result != SL_STATUS_OK) { - SILABS_LOG("*ERR*Send enet %d", (int) framelength); + ChipLogProgress(DeviceLayer, "*ERR*Send enet %d", (int) framelength); return ERR_IF; } return ERR_OK; @@ -312,7 +309,7 @@ void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer) buffer = (uint8_t *) &(rx_buffer->body.frame[rx_buffer->body.frame_padding]); #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("WF200: In %d", (int) len); + ChipLogProgress(DeviceLayer, "WF200: In %d", (int) len); #endif low_level_input(netif, buffer, len); @@ -320,14 +317,14 @@ void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer) else { #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("WF200: NO-INTF"); + ChipLogProgress(DeviceLayer, "WF200: NO-INTF"); #endif } } else { #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("WF200: Invalid frame IN"); + ChipLogProgress(DeviceLayer, "WF200: Invalid frame IN"); #endif } } @@ -360,7 +357,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) uint16_t framelength = 0; uint16_t datalength = 0; #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("LWIP : low_level_output"); + ChipLogProgress(DeviceLayer, "LWIP : low_level_output"); #endif if (xSemaphoreTake(ethout_sem, portMAX_DELAY) != pdTRUE) { @@ -376,11 +373,11 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) framelength = LWIP_FRAME_ALIGNMENT; } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("EN-RSI: Output"); + ChipLogProgress(DeviceLayer, "EN-RSI: Output"); #endif if ((netif->flags & (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) != (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) { - SILABS_LOG("EN-RSI:NOT UP"); + ChipLogProgress(DeviceLayer, "EN-RSI:NOT UP"); xSemaphoreGive(ethout_sem); return ERR_IF; } @@ -395,7 +392,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) if (!packet) #endif // SLI_SI91X_MCU_INTERFACE { - SILABS_LOG("EN-RSI:No buf"); + ChipLogProgress(DeviceLayer, "EN-RSI:No buf"); xSemaphoreGive(ethout_sem); #if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) return SL_STATUS_ALLOCATION_FAILED; @@ -407,8 +404,8 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) #endif // SLI_SI91X_MCU_INTERFACE #ifdef WIFI_DEBUG_ENABLED uint8_t * b = (uint8_t *) p->payload; - SILABS_LOG("EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], b[1], b[2], b[3], - b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]); + ChipLogProgress(DeviceLayer, "EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], + b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]); #endif /* Generate the packet */ for (q = p, datalength = 0; q != NULL; q = q->next) @@ -422,7 +419,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) wfx_rsi_pkt_add_data(packet, (uint8_t *) (p->payload), LWIP_FRAME_ALIGNMENT - datalength, datalength); } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("EN-RSI: Sending %d", framelength); + ChipLogProgress(DeviceLayer, "EN-RSI: Sending %d", framelength); #endif /* forward the generated packet to RSI to @@ -439,13 +436,13 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) if (wfx_rsi_send_data(packet, datalength)) #endif { - SILABS_LOG("*ERR*EN-RSI:Send fail"); + ChipLogProgress(DeviceLayer, "*ERR*EN-RSI:Send fail"); xSemaphoreGive(ethout_sem); return ERR_IF; } #ifdef WIFI_DEBUG_ENABLED - SILABS_LOG("EN-RSI:Xmit %d", framelength); + ChipLogProgress(DeviceLayer, "EN-RSI:Xmit %d", framelength); #endif xSemaphoreGive(ethout_sem); diff --git a/src/platform/silabs/efr32/wifi/lwip_netif.cpp b/src/platform/silabs/efr32/wifi/lwip_netif.cpp index ac91ad7a14ed75..3a0d104a90be71 100644 --- a/src/platform/silabs/efr32/wifi/lwip_netif.cpp +++ b/src/platform/silabs/efr32/wifi/lwip_netif.cpp @@ -28,7 +28,6 @@ #include "wfx_host_events.h" #include "wifi_config.h" -#include "AppConfig.h" #include "dhcp_client.h" #include "ethernetif.h" @@ -36,6 +35,7 @@ #include "event_groups.h" #include "task.h" +#include #include using namespace ::chip; using namespace ::chip::DeviceLayer; diff --git a/src/platform/silabs/efr32/wifi/wfx_notify.cpp b/src/platform/silabs/efr32/wifi/wfx_notify.cpp index f888a1a4c5c0ab..fd183100e7b913 100644 --- a/src/platform/silabs/efr32/wifi/wfx_notify.cpp +++ b/src/platform/silabs/efr32/wifi/wfx_notify.cpp @@ -26,8 +26,6 @@ #include "em_usart.h" #include "gpiointerrupt.h" -#include "AppConfig.h" - #include "FreeRTOS.h" #include "event_groups.h" #include "task.h" @@ -38,10 +36,10 @@ #include "wfx_rsi.h" #endif -#include -// #include #include #include +#include +#include using namespace ::chip; using namespace ::chip::DeviceLayer; @@ -65,8 +63,6 @@ void wfx_started_notify() sl_wfx_startup_ind_t evt; sl_wfx_mac_address_t mac; - SILABS_LOG("%s: started.", __func__); - memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_STARTUP_IND_ID; evt.header.length = sizeof evt; @@ -90,15 +86,13 @@ void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap) { sl_wfx_connect_ind_t evt; - SILABS_LOG("%s: started.", __func__); - if (status != SUCCESS_STATUS) { - SILABS_LOG("%s: error: failed status: %d.", __func__, status); + ChipLogProgress(DeviceLayer, "%s: error: failed status: %ld.", __func__, status); return; } - SILABS_LOG("%s: connected.", __func__); + ChipLogProgress(DeviceLayer, "%s: connected.", __func__); memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_CONNECT_IND_ID; @@ -123,8 +117,6 @@ void wfx_disconnected_notify(int32_t status) { sl_wfx_disconnect_ind_t evt; - SILABS_LOG("%s: started.", __func__); - memset(&evt, 0, sizeof(evt)); evt.header.id = SL_WFX_DISCONNECT_IND_ID; evt.header.length = sizeof evt; @@ -143,8 +135,6 @@ void wfx_ipv6_notify(int got_ip) { sl_wfx_generic_message_t eventData; - SILABS_LOG("%s: started.", __func__); - memset(&eventData, 0, sizeof(eventData)); eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP; eventData.header.length = sizeof(eventData.header); @@ -172,8 +162,6 @@ void wfx_ip_changed_notify(int got_ip) { sl_wfx_generic_message_t eventData; - SILABS_LOG("%s: started.", __func__); - memset(&eventData, 0, sizeof(eventData)); eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP; eventData.header.length = sizeof(eventData.header); @@ -206,12 +194,12 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry */ if (retryJoin < MAX_JOIN_RETRIES_COUNT) { - SILABS_LOG("%s: Next attempt after %d Seconds", __func__, CONVERT_MS_TO_SEC(WLAN_RETRY_TIMER_MS)); + ChipLogProgress(DeviceLayer, "%s: Next attempt after %d Seconds", __func__, CONVERT_MS_TO_SEC(WLAN_RETRY_TIMER_MS)); vTaskDelay(pdMS_TO_TICKS(WLAN_RETRY_TIMER_MS)); } else { - SILABS_LOG("Connect failed after max %d tries", retryJoin); + ChipLogProgress(DeviceLayer, "Connect failed after max %d tries", retryJoin); } } else @@ -225,7 +213,7 @@ void wfx_retry_interval_handler(bool is_wifi_disconnection_event, uint16_t retry { retryInterval = WLAN_MAX_RETRY_TIMER_MS; } - SILABS_LOG("%s: Next attempt after %d Seconds", __func__, CONVERT_MS_TO_SEC(retryInterval)); + ChipLogProgress(DeviceLayer, "%s: Next attempt after %ld Seconds", __func__, CONVERT_MS_TO_SEC(retryInterval)); vTaskDelay(pdMS_TO_TICKS(retryInterval)); retryInterval += retryInterval; } diff --git a/src/platform/silabs/rs911x/wfx_sl_ble_init.c b/src/platform/silabs/rs911x/wfx_sl_ble_init.c index 7e7c165043a71a..23bc666b20b528 100644 --- a/src/platform/silabs/rs911x/wfx_sl_ble_init.c +++ b/src/platform/silabs/rs911x/wfx_sl_ble_init.c @@ -160,7 +160,6 @@ void rsi_ble_on_event_indication_confirmation(uint16_t resp_status, rsi_ble_set_ */ void rsi_ble_on_read_req_event(uint16_t event_id, rsi_ble_read_req_t * rsi_ble_read_req) { - SILABS_LOG("%s: starting", __func__); event_msg.event_id = event_id; memcpy(&event_msg.rsi_ble_read_req, rsi_ble_read_req, sizeof(rsi_ble_read_req_t)); rsi_ble_app_set_event(RSI_BLE_EVENT_GATT_RD); From d9cbc1f754dfad80e490d45ecd0f82300acb0f5e Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 9 May 2024 14:09:32 -0400 Subject: [PATCH 25/39] Improve server logging on subscription failures. (#33372) * Improve server logging on subscription failures. 1) When logging "session inactive", log which session it is. 2) When a subscription ReadHandler closes, log the relevant subscription ID and peer node. * Address review comment. --- src/app/ReadHandler.cpp | 10 ++++++++++ src/messaging/ExchangeMgr.cpp | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 461add0f2dc150..dd4c928a1bafa1 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -175,6 +175,16 @@ void ReadHandler::Close(CloseOptions options) } } #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS + +#if CHIP_PROGRESS_LOGGING + if (IsType(InteractionType::Subscribe)) + { + const ScopedNodeId & peer = mSessionHandle ? mSessionHandle->GetPeer() : ScopedNodeId(); + ChipLogProgress(DataManagement, "Subscription id 0x%" PRIx32 " from node " ChipLogFormatScopedNodeId " torn down", + mSubscriptionId, ChipLogValueScopedNodeId(peer)); + } +#endif // CHIP_PROGRESS_LOGGING + MoveToState(HandlerState::AwaitingDestruction); mManagementCallback.OnDone(*this); } diff --git a/src/messaging/ExchangeMgr.cpp b/src/messaging/ExchangeMgr.cpp index a184723726781e..c60b948c87f814 100644 --- a/src/messaging/ExchangeMgr.cpp +++ b/src/messaging/ExchangeMgr.cpp @@ -106,8 +106,13 @@ ExchangeContext * ExchangeManager::NewContext(const SessionHandle & session, Exc { if (!session->IsActiveSession()) { +#if CHIP_ERROR_LOGGING + const ScopedNodeId & peer = session->GetPeer(); + ChipLogError(ExchangeManager, "NewContext failed: session %u to " ChipLogFormatScopedNodeId " is inactive", + session->SessionIdForLogging(), ChipLogValueScopedNodeId(peer)); +#endif // CHIP_ERROR_LOGGING + // Disallow creating exchange on an inactive session - ChipLogError(ExchangeManager, "NewContext failed: session inactive"); return nullptr; } return mContextPool.CreateObject(this, mNextExchangeId++, session, isInitiator, delegate); From 4cea6a9c237f63bf207f3fbe22a6abb0d1622710 Mon Sep 17 00:00:00 2001 From: Sharad Binjola <31142146+sharadb-amazon@users.noreply.github.com> Date: Thu, 9 May 2024 11:12:24 -0700 Subject: [PATCH 26/39] iOS tv-casting-app: deleting dead code (#33394) --- .../CastingServerBridge.mm | 2707 ----------------- .../CommissionerDiscoveryDelegateImpl.h | 160 - .../MatterTvCastingBridge/ConversionUtils.hpp | 65 - .../MatterTvCastingBridge/ConversionUtils.mm | 218 -- 4 files changed, 3150 deletions(-) delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.hpp delete mode 100644 examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm deleted file mode 100644 index f199ba96b7a5a5..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CastingServerBridge.mm +++ /dev/null @@ -1,2707 +0,0 @@ -/** - * - * Copyright (c) 2020-2023 Project CHIP Authors - * - * 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. - */ - -#import "CastingServerBridge.h" -#import "CastingServer.h" - -#import "CommissionableDataProviderImpl.hpp" -#import "CommissionerDiscoveryDelegateImpl.h" -#import "ConversionUtils.hpp" -#import "DeviceAttestationCredentialsProviderImpl.hpp" -#import "MatterCallbacks.h" -#import "OnboardingPayload.h" - -#include -#include -#include -#include -#include -#include - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021 -#endif - -#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR -#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00 -#endif - -@interface CastingServerBridge () - -@property AppParameters * appParameters; - -@property OnboardingPayload * _Nonnull onboardingPayload; - -@property CommissionableDataProviderImpl * commissionableDataProvider; - -@property chip::Credentials::DeviceAttestationCredentialsProvider * deviceAttestationCredentialsProvider; - -@property chip::CommonCaseDeviceServerInitParams * serverInitParams; - -@property CommissionerDiscoveryDelegateImpl * commissionerDiscoveryDelegate; - -@property TargetVideoPlayerInfo * previouslyConnectedVideoPlayer; - -// queue used to serialize all work performed by the CastingServerBridge -@property (atomic) dispatch_queue_t chipWorkQueue; - -@property NSMutableDictionary * subscriptionEstablishedCallbacks; - -@property NSMutableDictionary * subscriptionReadSuccessCallbacks; - -@property NSMutableDictionary * subscriptionReadFailureCallbacks; - -@property NSMutableDictionary * readSuccessCallbacks; - -@property NSMutableDictionary * readFailureCallbacks; - -@end - -@implementation CastingServerBridge - -+ (CastingServerBridge * _Nullable)getSharedInstance -{ - static CastingServerBridge * instance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - instance = [[self alloc] init]; - }); - return instance; -} - -- (instancetype)init -{ - if (self = [super init]) { - CHIP_ERROR err = chip::Platform::MemoryInit(); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "MemoryInit failed: %s", ErrorStr(err)); - return nil; - } - - // TODO: Constructors should not perform heavy work like initializing the Matter SDK. This should - // be moved to initializeApp or another suitable location. - err = chip::DeviceLayer::PlatformMgr().InitChipStack(); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "InitChipStack failed: %s", ErrorStr(err)); - return nil; - } - - _commissionerDiscoveryDelegate = new CommissionerDiscoveryDelegateImpl(); - - _subscriptionEstablishedCallbacks = [NSMutableDictionary dictionary]; - _subscriptionReadSuccessCallbacks = [NSMutableDictionary dictionary]; - _subscriptionReadFailureCallbacks = [NSMutableDictionary dictionary]; - _readSuccessCallbacks = [NSMutableDictionary dictionary]; - _readFailureCallbacks = [NSMutableDictionary dictionary]; - } - return self; -} - -/** - Dispatches the block on the Matter SDK dispatch queue. - - @param description Optional. A description of the callback to be dispatched for diagnostic purposes. - @param block The Block to be dispatched. - */ -- (void)dispatchOnMatterSDKQueue:(const NSString * _Nullable)description block:(dispatch_block_t)block -{ - if (nil != description) { - ChipLogProgress(AppServer, "[SYNC] CastingServerBridge %s", [description UTF8String]); - } - dispatch_async(_chipWorkQueue, ^{ - // The Matter SDK is not, generally, internally thread-safe. It relies upon the client to lock - // the SDK prior to any interactions after chip::DeviceLayer::PlatformMgr().InitChipStack() - // - // Note that it is presently safe to do at this point because InitChipStack is called in the - // constructor for the CastingServerBridge. - chip::DeviceLayer::StackLock lock; - - if (nil != description) { - ChipLogProgress(AppServer, "[ASYNC (CHIP)] CastingServerBridge BEGIN %s", [description UTF8String]); - } - block(); - if (nil != description) { - ChipLogProgress(AppServer, "[ASYNC (CHIP)] CastingServerBridge END %s", [description UTF8String]); - } - }); -} - -/** - Dispatches a client callback via a `dispatch_block_t` to be run on the client's `dispatch_queue_t`. - - @param queue The client's Dispatch Queue. - @param description Optional. A description of the callback to be dispatched for diagnostic purposes. - @param block The Block to be invoked to invoke the client callback. - */ -- (void)dispatchOnClientQueue:(dispatch_queue_t)queue - description:(const NSString * _Nullable)description - block:(dispatch_block_t)block -{ - // Within the CastingServerBridge, the usage pattern is typically to expose asynchronous public APIs that - // take a callback to indicate that the low-level SDK operation has been initiated (the "started" - // callback), and a separate set of result callbacks to be invoked when the low-level SDK operation - // has been completed (the "result" callbacks). - // - // All of the work is serialized on the _chipWorkQueue, with the started callback being invoked after the - // Matter SDK is called with the result callbacks. This poses a challenge because we don't have a strong - // guarantee that the Matter SDK will not complete its work and invoke the result callback before control - // is returning to the _chipWorkQueue thread; this can cause callbacks to be received in an unexpected - // order, where the result might arrive before the client knows that the call was started. - // - // To avoid this confusion, we perform a "double async" dispatch to ensure that events are delivered in a - // sensible order. First, we schedule the result callback to run on the _chipWorkQueue (so it *must* run - // after the end of the CastingServerBridge's wrapper logic that already started on the _chipWorkQueue) - // and then immediately, asynchronously dispatch the callback onto the provided client queue. - dispatch_async(_chipWorkQueue, ^{ - if (nil != description) { - ChipLogProgress(AppServer, "[ASYNC (CHIP)] CastingServerBridge dispatching %s", [description UTF8String]); - } - dispatch_async(queue, ^{ - if (nil != description) { - ChipLogProgress(AppServer, "[ASYNC (CLIENT)] CastingServerBridge BEGIN %s", [description UTF8String]); - } - block(); - if (nil != description) { - ChipLogProgress(AppServer, "[ASYNC (CLIENT)] CastingServerBridge END %s", [description UTF8String]); - } - }); - }); -} - -/** - A utility function that invokes an Objective C Block on the Matter Dispatch Queue in a thread-safe manner. - - The result of the Objective C Block will be relayed to the `blockCompleteCallback`. - - @param description Optional. A description of the Objective C Block to be invoked for diagnostic purposes. - @param callbackQueue The Dispatch Queue on which the callback shall be invoked. - @param blockCompleteCallback The callback to be invoked with the result of the Objective C Block. - @param block The Objective C Block to dispatch. - */ -- (void)withCastingServerInvokeBlock:(const NSString * _Nullable)description - callbackQueue:(dispatch_queue_t)callbackQueue - onBlockComplete:(void (^_Nonnull)(bool))blockCompleteCallback - block:(CHIP_ERROR (^_Nonnull)(CastingServer *))block -{ - [self dispatchOnMatterSDKQueue:description - block:^{ - CastingServer * castingServer = CastingServer::GetInstance(); - - // We invoke the block and capture the result on the Matter Dispatch Queue with the stack lock - // held, then use the result snapshot in the subsequent block to be asynchronously dispatched on - // the client's callback Dispatch Queue. - const CHIP_ERROR result = block(castingServer); - dispatch_async(callbackQueue, ^{ - if (nil != description) { - ChipLogProgress(AppServer, - "[ASYNC (CLIENT)] CastingServerBridge invoking %s Started Callback", - [description UTF8String]); - } - blockCompleteCallback( - [[MatterError alloc] initWithCode:result.AsInteger() - message:[NSString stringWithUTF8String:result.AsString()]]); - if (nil != description) { - ChipLogProgress(AppServer, - "[ASYNC (CLIENT)] CastingServerBridge invoked %s Started Callback", - [description UTF8String]); - } - }); - }]; -} - -/** - A utility function that invokes an Objective C Block on the Matter Dispatch Queue in a thread-safe manner. - - The result of the Objective C Block will be relayed to the `blockCompleteCallback`. The response callback is expected to be called - at a later time with the asynchronous result of the Casting Server operation (by the Casting Server). - - @param description Optional. A description of the Objective C Block to be invoked for diagnostic purposes. - @param blockCompleteCallback The callback to be invoked with the result of the Objective C Block. - @param responseCallback The callback that will eventually be invoked by the Casting Server when the operation has completed on the - remote end. - @param callbackQueue The Dispatch Queue on which the callbacks shall be invoked. - @param block The Objective C Block to dispatch. - */ -- (void)withCastingServerInvokeBlock:(const NSString * _Nullable)description - callbackQueue:(dispatch_queue_t)callbackQueue - onBlockComplete:(void (^_Nonnull)(bool))blockCompleteCallback - onResponse:(void (^_Nonnull)(bool))responseCallback - block:(CHIP_ERROR (^_Nonnull)(CastingServer *, std::function))block -{ - [self withCastingServerInvokeBlock:description - callbackQueue:callbackQueue - onBlockComplete:blockCompleteCallback - block:^(CastingServer * castingServer) { - return block(castingServer, [description, responseCallback, callbackQueue](CHIP_ERROR err) { - NSString * _description = description == nil - ? nil - : [NSString stringWithFormat:@"%@ Response Callback", description]; - - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:callbackQueue - description:_description - block:^{ - responseCallback(CHIP_NO_ERROR == err); - }]; - }); - }]; -} - -- (MatterError *)initializeApp:(AppParameters * _Nullable)appParameters - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - initAppStatusHandler:(nullable void (^)(bool))initAppStatusHandler -{ - // The Matter SDK is not, generally, internally thread-safe. It relies upon the client to lock - // the SDK prior to any interactions after chip::DeviceLayer::PlatformMgr().InitChipStack() - // - // Note that it is presently safe to do at this point because InitChipStack is called in the - // constructor for the CastingServerBridge. - chip::DeviceLayer::StackLock lock; - ChipLogProgress(AppServer, "CastingServerBridge().initApp() called"); - - CHIP_ERROR err = CHIP_NO_ERROR; - _commissionableDataProvider = new CommissionableDataProviderImpl(); - - _appParameters = appParameters; - AppParams cppAppParams; - uint32_t setupPasscode = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE; - uint16_t setupDiscriminator = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR; - uint32_t spake2pIterationCount; - chip::ByteSpan spake2pSaltSpan, spake2pVerifierSpan; - if (_appParameters != nil) { - err = [ConversionUtils convertToCppAppParamsInfoFrom:_appParameters outAppParams:cppAppParams]; - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "AppParameters conversion failed: %s", ErrorStr(err)); - return [[MatterError alloc] initWithCode:err.AsInteger() message:[NSString stringWithUTF8String:err.AsString()]]; - } - - // set fields in commissionableDataProvider - if (_appParameters.onboardingPayload != nil) { - setupPasscode = _appParameters.onboardingPayload.setupPasscode > 0 ? _appParameters.onboardingPayload.setupPasscode - : CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE; - setupDiscriminator = _appParameters.onboardingPayload.setupDiscriminator > 0 - ? _appParameters.onboardingPayload.setupDiscriminator - : CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR; - } - spake2pIterationCount = _appParameters.spake2pIterationCount; - if (_appParameters.spake2pSaltBase64 != nil) { - spake2pSaltSpan = chip::ByteSpan( - static_cast(_appParameters.spake2pSaltBase64.bytes), _appParameters.spake2pSaltBase64.length); - } - - if (_appParameters.spake2pVerifierBase64 != nil) { - chip::ByteSpan spake2pVerifierSpan - = chip::ByteSpan(static_cast(_appParameters.spake2pVerifierBase64.bytes), - _appParameters.spake2pVerifierBase64.length); - } - - err = _commissionableDataProvider->Initialize(_appParameters.spake2pVerifierBase64 != nil ? &spake2pVerifierSpan : nil, - _appParameters.spake2pSaltBase64 != nil ? &spake2pSaltSpan : nil, spake2pIterationCount, setupPasscode, - setupDiscriminator); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "Failed to initialize CommissionableDataProvider: %s", ErrorStr(err)); - return [[MatterError alloc] initWithCode:err.AsInteger() message:[NSString stringWithUTF8String:err.AsString()]]; - } - } - chip::DeviceLayer::SetCommissionableDataProvider(_commissionableDataProvider); - - _commissionableDataProvider->GetSetupPasscode(setupPasscode); - _commissionableDataProvider->GetSetupDiscriminator(setupDiscriminator); - _onboardingPayload = [[OnboardingPayload alloc] initWithSetupPasscode:setupPasscode setupDiscriminator:setupDiscriminator]; - - // Initialize device attestation verifier from a constant version - { - // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available - const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); - SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); - } - - // init app Server - _serverInitParams = new chip::CommonCaseDeviceServerInitParams(); - err = _serverInitParams->InitializeStaticResourcesBeforeServerInit(); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "InitializeStaticResourcesBeforeServerInit failed: %s", ErrorStr(err)); - return [[MatterError alloc] initWithCode:err.AsInteger() message:[NSString stringWithUTF8String:err.AsString()]]; - } - - AppParams appParam; - if (appParameters == nil) { - err = CastingServer::GetInstance()->PreInit(); - } else if ((err = [ConversionUtils convertToCppAppParamsInfoFrom:appParameters outAppParams:appParam]) == CHIP_NO_ERROR) { - err = CastingServer::GetInstance()->PreInit(&appParam); - } - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "CastingServer PreInit failed: %s", ErrorStr(err)); - return [[MatterError alloc] initWithCode:err.AsInteger() message:[NSString stringWithUTF8String:err.AsString()]]; - } - - err = chip::Server::GetInstance().Init(*_serverInitParams); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "chip::Server init failed: %s", ErrorStr(err)); - return [[MatterError alloc] initWithCode:err.AsInteger() message:[NSString stringWithUTF8String:err.AsString()]]; - } - - _chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue(); - - chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask(); - - dispatch_async(_chipWorkQueue, ^{ - CHIP_ERROR err = CHIP_NO_ERROR; - AppParams appParam; - if (appParameters == nil) { - err = CastingServer::GetInstance()->Init(); - } else if ((err = [ConversionUtils convertToCppAppParamsInfoFrom:appParameters outAppParams:appParam]) == CHIP_NO_ERROR) { - err = CastingServer::GetInstance()->Init(&appParam); - } - - Boolean initAppStatus = true; - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "CastingServerBridge().initApp() failed: %" CHIP_ERROR_FORMAT, err.Format()); - initAppStatus = false; - } - - dispatch_async(clientQueue, ^{ - initAppStatusHandler(initAppStatus); - }); - }); - - return [[MatterError alloc] initWithCode:CHIP_NO_ERROR.AsInteger() - message:[NSString stringWithUTF8String:CHIP_NO_ERROR.AsString()]]; -} - -- (void)setDacHolder:(DeviceAttestationCredentialsHolder * _Nonnull)deviceAttestationCredentials - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - setDacHolderStatus:(void (^_Nonnull)(MatterError * _Nonnull))setDacHolderStatus -{ - dispatch_sync(_chipWorkQueue, ^{ - NSData * certificationDeclarationNsData = deviceAttestationCredentials.getCertificationDeclaration; - chip::MutableByteSpan certificationDeclaration - = chip::MutableByteSpan(const_cast(static_cast(certificationDeclarationNsData.bytes)), - certificationDeclarationNsData.length); - - NSData * firmwareInformationNsData = deviceAttestationCredentials.getFirmwareInformation; - chip::MutableByteSpan firmwareInformation = chip::MutableByteSpan( - const_cast(static_cast(firmwareInformationNsData.bytes)), firmwareInformationNsData.length); - - NSData * deviceAttestationCertNsData = deviceAttestationCredentials.getDeviceAttestationCert; - chip::MutableByteSpan deviceAttestationCert - = chip::MutableByteSpan(const_cast(static_cast(deviceAttestationCertNsData.bytes)), - deviceAttestationCertNsData.length); - - NSData * productAttestationIntermediateCertNsData = deviceAttestationCredentials.getProductAttestationIntermediateCert; - chip::MutableByteSpan productAttestationIntermediateCert = chip::MutableByteSpan( - const_cast(static_cast(productAttestationIntermediateCertNsData.bytes)), - productAttestationIntermediateCertNsData.length); - - self->_deviceAttestationCredentialsProvider - = new DeviceAttestationCredentialsProviderImpl(&certificationDeclaration, &firmwareInformation, &deviceAttestationCert, - &productAttestationIntermediateCert, deviceAttestationCredentials.getDeviceAttestationCertPrivateKeyRef); - - SetDeviceAttestationCredentialsProvider(self->_deviceAttestationCredentialsProvider); - - dispatch_async(clientQueue, ^{ - setDacHolderStatus([[MatterError alloc] initWithCode:CHIP_NO_ERROR.AsInteger() - message:[NSString stringWithUTF8String:CHIP_NO_ERROR.AsString()]]); - }); - }); -} - -- (void)discoverCommissioners:(dispatch_queue_t _Nonnull)clientQueue - discoveryRequestSentHandler:(nullable void (^)(bool))discoveryRequestSentHandler - discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData *))discoveredCommissionerHandler -{ - [self dispatchOnMatterSDKQueue:@"discoverCommissioners(...)" - block:^{ - bool discoveryRequestStatus = true; - - if (discoveredCommissionerHandler != nil) { - TargetVideoPlayerInfo * cachedTargetVideoPlayerInfos - = CastingServer::GetInstance()->ReadCachedTargetVideoPlayerInfos(); - self->_commissionerDiscoveryDelegate->SetUp( - clientQueue, discoveredCommissionerHandler, cachedTargetVideoPlayerInfos); - } - CHIP_ERROR err = CastingServer::GetInstance()->DiscoverCommissioners( - discoveredCommissionerHandler != nil ? self->_commissionerDiscoveryDelegate : nullptr); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, - "CastingServerBridge().discoverCommissioners() failed: %" CHIP_ERROR_FORMAT, err.Format()); - discoveryRequestStatus = false; - } - - dispatch_async(clientQueue, ^{ - discoveryRequestSentHandler(discoveryRequestStatus); - }); - }]; -} - -- (void)getDiscoveredCommissioner:(int)index - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - discoveredCommissionerHandler:(nullable void (^)(DiscoveredNodeData * _Nullable))discoveredCommissionerHandler -{ - [self dispatchOnMatterSDKQueue:@"getDiscoveredCommissioner(...)" - block:^{ - chip::Optional associatedConnectableVideoPlayer; - DiscoveredNodeData * commissioner = nil; - const chip::Dnssd::CommissionNodeData * cppDiscoveredNodeData - = CastingServer::GetInstance()->GetDiscoveredCommissioner( - index, associatedConnectableVideoPlayer); - if (cppDiscoveredNodeData != nullptr) { - commissioner = [ConversionUtils convertToObjCDiscoveredNodeDataFrom:cppDiscoveredNodeData]; - if (associatedConnectableVideoPlayer.HasValue()) { - VideoPlayer * connectableVideoPlayer = [ConversionUtils - convertToObjCVideoPlayerFrom:associatedConnectableVideoPlayer.Value()]; - [commissioner setConnectableVideoPlayer:connectableVideoPlayer]; - } - } - - dispatch_async(clientQueue, ^{ - discoveredCommissionerHandler(commissioner); - }); - }]; -} - -- (void)sendUserDirectedCommissioningRequest:(NSString * _Nonnull)commissionerIpAddress - commissionerPort:(uint16_t)commissionerPort - platformInterface:(unsigned int)platformInterface - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler -{ - const NSString * description = - [NSString stringWithFormat:@"sendUserDirectedCommissioningRequest() IP %s port %d platformInterface %d", - [commissionerIpAddress UTF8String], commissionerPort, platformInterface]; - [self dispatchOnMatterSDKQueue:description - block:^{ - bool udcRequestStatus; - chip::Inet::IPAddress commissionerAddrInet; - if (chip::Inet::IPAddress::FromString([commissionerIpAddress UTF8String], commissionerAddrInet) - == false) { - ChipLogError(AppServer, - "CastingServerBridge().sendUserDirectedCommissioningRequest() failed to parse IP address"); - udcRequestStatus = false; - } else { - chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId(platformInterface); - - chip::Transport::PeerAddress commissionerPeerAddress - = chip::Transport::PeerAddress::UDP(commissionerAddrInet, commissionerPort, interfaceId); - - CHIP_ERROR err = CastingServer::GetInstance()->SendUserDirectedCommissioningRequest( - commissionerPeerAddress); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, - "CastingServerBridge().sendUserDirectedCommissioningRequest() failed: " - "%" CHIP_ERROR_FORMAT, - err.Format()); - udcRequestStatus = false; - } else { - udcRequestStatus = true; - } - } - - dispatch_async(clientQueue, ^{ - udcRequestSentHandler(udcRequestStatus); - }); - }]; -} - -- (void)sendUserDirectedCommissioningRequest:(DiscoveredNodeData * _Nonnull)commissioner - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - udcRequestSentHandler:(nullable void (^)(bool))udcRequestSentHandler -{ - const NSString * description = - [NSString stringWithFormat:@"sendUserDirectedCommissioningRequest(...) IP %s port %d platformInterface %d deviceName %s", - [commissioner.ipAddresses[0] UTF8String], commissioner.port, commissioner.platformInterface, - [commissioner.deviceName UTF8String]]; - - [self dispatchOnMatterSDKQueue:description - block:^{ - bool udcRequestStatus; - - chip::Dnssd::CommissionNodeData cppCommissioner; - if ([ConversionUtils convertToCppDiscoveredNodeDataFrom:commissioner - outDiscoveredNodeData:cppCommissioner] - != CHIP_NO_ERROR) { - ChipLogError(AppServer, - "CastingServerBridge().sendUserDirectedCommissioningRequest() failed to convert " - "Commissioner(DiscoveredNodeData) " - "to Cpp type"); - udcRequestStatus = false; - } else { - CHIP_ERROR err - = CastingServer::GetInstance()->SendUserDirectedCommissioningRequest(&cppCommissioner); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, - "CastingServerBridge().sendUserDirectedCommissioningRequest() failed: " - "%" CHIP_ERROR_FORMAT, - err.Format()); - udcRequestStatus = false; - } else { - udcRequestStatus = true; - } - } - - dispatch_async(clientQueue, ^{ - udcRequestSentHandler(udcRequestStatus); - }); - }]; -} - -- (OnboardingPayload *)getOnboardingPayload -{ - return _onboardingPayload; -} - -- (void)openBasicCommissioningWindow:(dispatch_queue_t _Nonnull)clientQueue - commissioningCallbackHandlers:(CommissioningCallbackHandlers * _Nullable)commissioningCallbackHandlers - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback -{ - [self - dispatchOnMatterSDKQueue:@"openBasicCommissioningWindow(...)" - block:^{ - CommissioningCallbacks commissioningCallbacks; - if (commissioningCallbackHandlers != nil) { - if (commissioningCallbackHandlers.commissioningCompleteCallback != nil) { - commissioningCallbacks.commissioningComplete = [clientQueue, commissioningCallbackHandlers]( - CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description: - @"openBasicCommissioningWindow(...) commissioningCompleteCallback" - block:^{ - commissioningCallbackHandlers.commissioningCompleteCallback( - CHIP_NO_ERROR == err); - }]; - }; - } - - if (commissioningCallbackHandlers.sessionEstablishmentStartedCallback != nil) { - commissioningCallbacks.sessionEstablishmentStarted - = [clientQueue, commissioningCallbackHandlers]() { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) " - @"sessionEstablishmentStartedCallback" - block:^{ - commissioningCallbackHandlers - .sessionEstablishmentStartedCallback(); - }]; - }; - } - - if (commissioningCallbackHandlers.sessionEstablishedCallback != nil) { - commissioningCallbacks.sessionEstablished = [clientQueue, commissioningCallbackHandlers]() { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) sessionEstablishedCallback" - block:^{ - commissioningCallbackHandlers.sessionEstablishedCallback(); - }]; - }; - } - - if (commissioningCallbackHandlers.sessionEstablishmentErrorCallback != nil) { - commissioningCallbacks.sessionEstablishmentError = [clientQueue, - commissioningCallbackHandlers]( - CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) " - @"sessionEstablishmentErrorCallback" - block:^{ - commissioningCallbackHandlers.sessionEstablishmentErrorCallback( - [[MatterError alloc] - initWithCode:err.AsInteger() - message:[NSString - stringWithUTF8String:err.AsString()]]); - }]; - }; - } - - if (commissioningCallbackHandlers.sessionEstablishmentStoppedCallback != nil) { - commissioningCallbacks.sessionEstablishmentStopped - = [clientQueue, commissioningCallbackHandlers]() { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) " - @"sessionEstablishmentStoppedCallback" - block:^{ - commissioningCallbackHandlers - .sessionEstablishmentStoppedCallback(); - }]; - }; - } - } - CHIP_ERROR err = CastingServer::GetInstance()->OpenBasicCommissioningWindow( - commissioningCallbacks, - [clientQueue, onConnectionSuccessCallback](TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { - VideoPlayer * videoPlayer = - [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) onConnectionSuccessCallback" - block:^{ - onConnectionSuccessCallback(videoPlayer); - }]; - }, - [clientQueue, onConnectionFailureCallback](CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) onConnectionFailureCallback" - block:^{ - onConnectionFailureCallback([[MatterError alloc] - initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }]; - }, - [clientQueue, onNewOrUpdatedEndpointCallback](TargetEndpointInfo * cppTargetEndpointInfo) { - ContentApp * contentApp = - [ConversionUtils convertToObjCContentAppFrom:cppTargetEndpointInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"openBasicCommissioningWindow(...) onNewOrUpdatedEndpointCallback" - block:^{ - onNewOrUpdatedEndpointCallback(contentApp); - }]; - }); - - if (commissioningCallbackHandlers != nil - && commissioningCallbackHandlers.commissioningWindowRequestedHandler != nil) { - dispatch_async(clientQueue, ^{ - ChipLogProgress(AppServer, "[async] Dispatching commissioningWindowRequestedHandler"); - commissioningCallbackHandlers.commissioningWindowRequestedHandler(CHIP_NO_ERROR == err); - }); - } - }]; -} - -- (void)getActiveTargetVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue - activeTargetVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))activeTargetVideoPlayersHandler -{ - [self dispatchOnMatterSDKQueue:@"getActiveTargetVideoPlayers(...)" - block:^{ - NSMutableArray * videoPlayers = [NSMutableArray new]; - TargetVideoPlayerInfo * cppTargetVideoPlayerInfo - = CastingServer::GetInstance()->GetActiveTargetVideoPlayer(); - if (cppTargetVideoPlayerInfo != nullptr && cppTargetVideoPlayerInfo->IsInitialized()) { - videoPlayers[0] = [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; - } - - dispatch_async(clientQueue, ^{ - activeTargetVideoPlayersHandler(videoPlayers); - }); - }]; -} - -- (void)readCachedVideoPlayers:(dispatch_queue_t _Nonnull)clientQueue - readCachedVideoPlayersHandler:(nullable void (^)(NSMutableArray * _Nullable))readCachedVideoPlayersHandler -{ - [self dispatchOnMatterSDKQueue:@"readCachedVideoPlayers(...)" - block:^{ - NSMutableArray * videoPlayers = nil; - TargetVideoPlayerInfo * cppTargetVideoPlayerInfos - = CastingServer::GetInstance()->ReadCachedTargetVideoPlayerInfos(); - if (cppTargetVideoPlayerInfos != nullptr) { - videoPlayers = [NSMutableArray new]; - for (size_t i = 0; cppTargetVideoPlayerInfos[i].IsInitialized(); i++) { - ChipLogProgress(AppServer, - "CastingServerBridge().readCachedVideoPlayers() with nodeId: 0x" ChipLogFormatX64 - " fabricIndex: %d deviceName: %s vendorId: %d", - ChipLogValueX64(cppTargetVideoPlayerInfos[i].GetNodeId()), - cppTargetVideoPlayerInfos[i].GetFabricIndex(), - cppTargetVideoPlayerInfos[i].GetDeviceName(), - cppTargetVideoPlayerInfos[i].GetVendorId()); - videoPlayers[i] = - [ConversionUtils convertToObjCVideoPlayerFrom:&cppTargetVideoPlayerInfos[i]]; - } - } - - dispatch_async(clientQueue, ^{ - readCachedVideoPlayersHandler(videoPlayers); - }); - }]; -} - -- (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(nullable void (^)(MatterError * _Nonnull))requestSentHandler - onConnectionSuccessCallback:(void (^_Nonnull)(VideoPlayer * _Nonnull))onConnectionSuccessCallback - onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback - onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback -{ - [self dispatchOnMatterSDKQueue:@"verifyOrEstablishConnection(...)" - block:^{ - TargetVideoPlayerInfo targetVideoPlayerInfo; - [ConversionUtils convertToCppTargetVideoPlayerInfoFrom:videoPlayer - outTargetVideoPlayerInfo:targetVideoPlayerInfo]; - - CHIP_ERROR err = CastingServer::GetInstance()->VerifyOrEstablishConnection( - targetVideoPlayerInfo, - [clientQueue, onConnectionSuccessCallback](TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { - VideoPlayer * videoPlayer = - [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onConnectionSuccessCallback" - block:^{ - onConnectionSuccessCallback(videoPlayer); - }]; - }, - [clientQueue, onConnectionFailureCallback](CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onConnectionFailureCallback" - block:^{ - onConnectionFailureCallback([[MatterError alloc] - initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }]; - }, - [clientQueue, onNewOrUpdatedEndpointCallback](TargetEndpointInfo * cppTargetEndpointInfo) { - ContentApp * contentApp = - [ConversionUtils convertToObjCContentAppFrom:cppTargetEndpointInfo]; - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"onNewOrUpdatedEndpointCallback" - block:^{ - onNewOrUpdatedEndpointCallback(contentApp); - }]; - }); - - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler -{ - [self dispatchOnMatterSDKQueue:@"shutdownAllSubscriptions(...)" - block:^{ - CastingServer::GetInstance()->ShutdownAllSubscriptions(); - dispatch_async(clientQueue, ^{ - requestSentHandler(); - }); - }]; -} - -- (void)startMatterServer:(dispatch_queue_t _Nonnull)clientQueue - startMatterServerCompletionCallback:(nullable void (^)(MatterError * _Nonnull))startMatterServerCompletionCallback -{ - [self dispatchOnMatterSDKQueue:@"startMatterServer(...)" - block:^{ - // Initialize the Matter server - CHIP_ERROR err = chip::Server::GetInstance().Init(*self->_serverInitParams); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "chip::Server init failed: %s", ErrorStr(err)); - dispatch_async(clientQueue, ^{ - startMatterServerCompletionCallback( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - return; - } - - // Initialize AppDelegation - CastingServer::GetInstance()->InitAppDelegation(); - - // Initialize binding handlers - err = CastingServer::GetInstance()->InitBindingHandlers(); - if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "Binding init failed: %s", ErrorStr(err)); - dispatch_async(clientQueue, ^{ - startMatterServerCompletionCallback( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - return; - } - - // Now reconnect to the VideoPlayer the casting app was previously connected to (if any) - if (self->_previouslyConnectedVideoPlayer != nil) { - ChipLogProgress(AppServer, - "CastingServerBridge().startMatterServer() reconnecting to previously connected " - "VideoPlayer..."); - err = CastingServer::GetInstance()->VerifyOrEstablishConnection( - *(self->_previouslyConnectedVideoPlayer), - [clientQueue, startMatterServerCompletionCallback]( - TargetVideoPlayerInfo * cppTargetVideoPlayerInfo) { - dispatch_async(clientQueue, ^{ - startMatterServerCompletionCallback([[MatterError alloc] - initWithCode:CHIP_NO_ERROR.AsInteger() - message:[NSString stringWithUTF8String:CHIP_NO_ERROR.AsString()]]); - }); - }, - [clientQueue, startMatterServerCompletionCallback](CHIP_ERROR err) { - dispatch_async(clientQueue, ^{ - startMatterServerCompletionCallback([[MatterError alloc] - initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }, - [](TargetEndpointInfo * cppTargetEndpointInfo) {}); - } else { - dispatch_async(clientQueue, ^{ - startMatterServerCompletionCallback([[MatterError alloc] - initWithCode:CHIP_NO_ERROR.AsInteger() - message:[NSString stringWithUTF8String:CHIP_NO_ERROR.AsString()]]); - }); - } - }]; -} - -- (void)stopMatterServer -{ - [self - dispatchOnMatterSDKQueue:@"stopMatterServer(...)" - block:^{ - // capture pointer to previouslyConnectedVideoPlayer, to be deleted - TargetVideoPlayerInfo * videoPlayerForDeletion - = self->_previouslyConnectedVideoPlayer == nil ? nil : self->_previouslyConnectedVideoPlayer; - - // On shutting down the Matter server, the casting app will be automatically disconnected from any - // Video Players it was connected to. Save the VideoPlayer that the casting app was targetting and - // connected to, so we can reconnect to it on re-starting the Matter server. - TargetVideoPlayerInfo * currentTargetVideoPlayerInfo - = CastingServer::GetInstance()->GetActiveTargetVideoPlayer(); - if (currentTargetVideoPlayerInfo != nil && currentTargetVideoPlayerInfo->IsInitialized() - && currentTargetVideoPlayerInfo->GetOperationalDeviceProxy() != nil) { - self->_previouslyConnectedVideoPlayer = new TargetVideoPlayerInfo(); - self->_previouslyConnectedVideoPlayer->Initialize(currentTargetVideoPlayerInfo->GetNodeId(), - currentTargetVideoPlayerInfo->GetFabricIndex(), nullptr, nullptr, - currentTargetVideoPlayerInfo->GetVendorId(), currentTargetVideoPlayerInfo->GetProductId(), - currentTargetVideoPlayerInfo->GetDeviceType(), currentTargetVideoPlayerInfo->GetDeviceName(), - currentTargetVideoPlayerInfo->GetHostName(), currentTargetVideoPlayerInfo->GetNumIPs(), - const_cast(currentTargetVideoPlayerInfo->GetIpAddresses())); - - TargetEndpointInfo * prevEndpoints = self->_previouslyConnectedVideoPlayer->GetEndpoints(); - if (prevEndpoints != nullptr) { - for (size_t i = 0; i < kMaxNumberOfEndpoints; i++) { - prevEndpoints[i].Reset(); - } - } - TargetEndpointInfo * currentEndpoints = currentTargetVideoPlayerInfo->GetEndpoints(); - for (size_t i = 0; i < kMaxNumberOfEndpoints && currentEndpoints[i].IsInitialized(); i++) { - prevEndpoints[i].Initialize(currentEndpoints[i].GetEndpointId()); - chip::ClusterId * currentClusters = currentEndpoints[i].GetClusters(); - for (size_t j = 0; - j < kMaxNumberOfClustersPerEndpoint && currentClusters[j] != chip::kInvalidClusterId; - j++) { - prevEndpoints[i].AddCluster(currentClusters[j]); - } - } - } else { - self->_previouslyConnectedVideoPlayer = nil; - } - - // Now shutdown the Matter server - chip::Server::GetInstance().Shutdown(); - - // Delete the old previouslyConnectedVideoPlayer, if non-nil - if (videoPlayerForDeletion != nil) { - delete videoPlayerForDeletion; - } - }]; -} - -- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler -{ - [self dispatchOnMatterSDKQueue:@"disconnect(...)" - block:^{ - CastingServer::GetInstance()->Disconnect(); - dispatch_async(clientQueue, ^{ - requestSentHandler(); - }); - }]; -} - -- (void)purgeCache:(dispatch_queue_t _Nonnull)clientQueue responseHandler:(void (^)(MatterError * _Nonnull))responseHandler -{ - dispatch_sync(_chipWorkQueue, ^{ - CHIP_ERROR err = CastingServer::GetInstance()->PurgeCache(); - dispatch_async(clientQueue, ^{ - responseHandler([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }); -} - -- (void)contentLauncher_launchUrl:(ContentApp * _Nonnull)contentApp - contentUrl:(NSString * _Nonnull)contentUrl - contentDisplayStr:(NSString * _Nonnull)contentDisplayStr - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - return castingServer->ContentLauncherLaunchURL( - &endpoint, [contentUrl UTF8String], [contentDisplayStr UTF8String], responseFunction); - }]; -} - -- (void)contentLauncher_launchContent:(ContentApp * _Nonnull)contentApp - contentSearch:(ContentLauncher_ContentSearch * _Nonnull)contentSearch - autoPlay:(bool)autoPlay - data:(NSString * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = - [NSString stringWithFormat:@"contentLauncher_launchContent(...) with Content App endpoint ID %d", contentApp.endpointId]; - - // Make a copy of params before we go async. - contentSearch = [contentSearch copy]; - data = [data copy]; - - [self - dispatchOnMatterSDKQueue:description - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - ListFreer listFreer; - chip::app::Clusters::ContentLauncher::Structs::ContentSearchStruct::Type cppSearch; - if (contentSearch.parameterList.count > 0) { - auto * parameterListHolder - = new ListHolder( - contentSearch.parameterList.count); - listFreer.add(parameterListHolder); - - int parameterIndex = 0; - for (ContentLauncher_Parameter * parameter in contentSearch.parameterList) { - int externalIdListIndex = 0; - if (parameter.externalIDList != nil) { - auto * externalIdListHolder = new ListHolder< - chip::app::Clusters::ContentLauncher::Structs::AdditionalInfoStruct::Type>( - parameter.externalIDList.count); - listFreer.add(externalIdListHolder); - - for (ContentLauncher_AdditionalInfo * additionalInfo in parameter.externalIDList) { - externalIdListHolder->mList[externalIdListIndex].value - = chip::CharSpan([additionalInfo.value UTF8String], - [additionalInfo.value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); - externalIdListHolder->mList[externalIdListIndex].name - = chip::CharSpan([additionalInfo.name UTF8String], - [additionalInfo.name lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); - externalIdListIndex++; - } - parameterListHolder->mList[parameterIndex].externalIDList - = MakeOptional(chip::app::DataModel::List< - const chip::app::Clusters::ContentLauncher::Structs::AdditionalInfoStruct::Type>( - externalIdListHolder->mList, parameter.externalIDList.count)); - } else { - parameterListHolder->mList[parameterIndex].externalIDList - = chip::Optional>::Missing(); - } - - parameterListHolder->mList[parameterIndex].type - = static_cast(parameter.type); - parameterListHolder->mList[parameterIndex].value - = chip::CharSpan([parameter.value UTF8String], - [parameter.value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); - parameterIndex++; - cppSearch.parameterList = chip::app::DataModel::List< - chip::app::Clusters::ContentLauncher::Structs::ParameterStruct::Type>( - parameterListHolder->mList, contentSearch.parameterList.count); - } - } - - CHIP_ERROR err = CastingServer::GetInstance()->ContentLauncher_LaunchContent(&endpoint, cppSearch, - autoPlay, - MakeOptional( - chip::CharSpan([data UTF8String], [data lengthOfBytesUsingEncoding:NSUTF8StringEncoding])), - [clientQueue, responseCallback](CHIP_ERROR err) { - [[CastingServerBridge getSharedInstance] - dispatchOnClientQueue:clientQueue - description:@"contentLauncher_launchContent(...) responseCallback" - block:^{ - responseCallback(CHIP_NO_ERROR == err); - }]; - }); - - dispatch_async(clientQueue, ^{ - requestSentHandler(CHIP_NO_ERROR == err); - }); - }]; -} - -- (void)contentLauncher_subscribeSupportedStreamingProtocols:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint32_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - const NSString * description = - [NSString stringWithFormat:@"contentLauncher_subscribeSupportedStreamingProtocols(...) with Content App endpoint ID %d", - contentApp.endpointId]; - [self dispatchOnMatterSDKQueue:description - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err - = CastingServer::GetInstance()->ContentLauncher_SubscribeToSupportedStreamingProtocols( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ContentLauncher::Attributes::SupportedStreamingProtocols:: - TypeInfo::DecodableArgType supportedStreamingProtocols) { - void (^callback)(uint32_t) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"contentLauncher_subscribeSupportedStreamingProtocols"]; - callback(supportedStreamingProtocols.Raw()); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"contentLauncher_subscribeSupportedStreamingProtocols"]; - callback( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"contentLauncher_subscribeSupportedStreamingProtocols"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)levelControl_step:(ContentApp * _Nonnull)contentApp - stepMode:(uint8_t)stepMode - stepSize:(uint8_t)stepSize - transitionTime:(uint16_t)transitionTime - optionMask:(uint8_t)optionMask - optionOverride:(uint8_t)optionOverride - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->LevelControl_Step(&endpoint, - static_cast(stepMode), stepSize, - transitionTime, optionMask, optionOverride, responseFunction); - }]; -} - -- (void)levelControl_moveToLevel:(ContentApp * _Nonnull)contentApp - level:(uint8_t)level - transitionTime:(uint16_t)transitionTime - optionMask:(uint8_t)optionMask - optionOverride:(uint8_t)optionOverride - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = - [NSString stringWithFormat:@"levelControl_moveToLevel(...) with Content App endpoint ID %d", contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->LevelControl_MoveToLevel( - &endpoint, level, transitionTime, optionMask, optionOverride, responseFunction); - }]; -} - -- (void)levelControl_subscribeCurrentLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().levelControl_subscribeCurrentLevel() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"levelControl_subscribeCurrentLevel"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"levelControl_subscribeCurrentLevel"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"levelControl_subscribeCurrentLevel"]; - - [self - dispatchOnMatterSDKQueue:@"levelControl_subscribeCurrentLevel(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->LevelControl_SubscribeToCurrentLevel( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo::DecodableArgType - currentLevel) { - void (^callback)(NSNumber * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"levelControl_subscribeCurrentLevel"]; - callback(@(currentLevel.Value())); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"levelControl_subscribeCurrentLevel"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"levelControl_subscribeCurrentLevel"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)levelControl_subscribeMinLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().levelControl_subscribeMinLevel() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"levelControl_subscribeMinLevel"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"levelControl_subscribeMinLevel"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"levelControl_subscribeMinLevel"]; - - [self - dispatchOnMatterSDKQueue:@"levelControl_subscribeMinLevel(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->LevelControl_SubscribeToMinLevel( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::LevelControl::Attributes::MinLevel::TypeInfo::DecodableArgType - minLevel) { - void (^callback)(uint8_t) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"levelControl_subscribeMinLevel"]; - callback(minLevel); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"levelControl_subscribeMinLevel"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"levelControl_subscribeMinLevel"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)levelControl_subscribeMaxLevel:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().levelControl_subscribeMaxLevel() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"levelControl_subscribeMaxLevel"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"levelControl_subscribeMaxLevel"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"levelControl_subscribeMaxLevel"]; - - [self - dispatchOnMatterSDKQueue:@"levelControl_subscribeMaxLevel(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->LevelControl_SubscribeToMaxLevel( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::LevelControl::Attributes::MaxLevel::TypeInfo::DecodableArgType - maxLevel) { - void (^callback)(uint8_t) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"levelControl_subscribeMaxLevel"]; - callback(maxLevel); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"levelControl_subscribeMaxLevel"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"levelControl_subscribeMaxLevel"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_play:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Play(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_pause:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Pause(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_stopPlayback:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_StopPlayback(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_next:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Next(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_seek:(ContentApp * _Nonnull)contentApp - position:(uint64_t)position - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Seek(&endpoint, position, responseFunction); - }]; -} - -- (void)mediaPlayback_skipForward:(ContentApp * _Nonnull)contentApp - deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_SkipForward( - &endpoint, deltaPositionMilliseconds, responseFunction); - }]; -} - -- (void)mediaPlayback_skipBackward:(ContentApp * _Nonnull)contentApp - deltaPositionMilliseconds:(uint64_t)deltaPositionMilliseconds - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_SkipBackward( - &endpoint, deltaPositionMilliseconds, responseFunction); - }]; -} - -- (void)mediaPlayback_previous:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Previous(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_rewind:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_Rewind(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_fastForward:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_FastForward(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_startOver:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->MediaPlayback_StartOver(&endpoint, responseFunction); - }]; -} - -- (void)mediaPlayback_subscribeCurrentState:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackState))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().mediaPlayback_subscribeCurrentState() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeCurrentState"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeCurrentState"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeCurrentState"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeCurrentState(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToCurrentState( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::CurrentState::TypeInfo::DecodableArgType - currentState) { - void (^callback)(MediaPlayback_PlaybackState) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeCurrentState"]; - callback(MediaPlayback_PlaybackState(currentState)); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeCurrentState"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeCurrentState"]; - callback(); - }); - - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribeStartTime:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_subscribeStartTime() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeStartTime"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeStartTime"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeStartTime"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeStartTime(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToStartTime( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::StartTime::TypeInfo::DecodableArgType - startTime) { - void (^callback)(NSNumber * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeStartTime"]; - callback(@(startTime.Value())); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeStartTime"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeStartTime"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribeDuration:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().mediaPlayback_subscribeDuration() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeDuration"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeDuration"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeDuration"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeDuration(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToDuration( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::Duration::TypeInfo::DecodableArgType - startTime) { - void (^callback)(NSNumber * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeDuration"]; - callback(@(startTime.Value())); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeDuration"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeDuration"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribeSampledPosition:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(MediaPlayback_PlaybackPosition * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().mediaPlayback_subscribeSampledPosition() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeSampledPosition"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeSampledPosition"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeSampledPosition"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeSampledPosition(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToSampledPosition( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::SampledPosition::TypeInfo::DecodableArgType - playbackPosition) { - void (^callback)(MediaPlayback_PlaybackPosition * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeSampledPosition"]; - MediaPlayback_PlaybackPosition * objCPlaybackPosition = nil; - if (!playbackPosition.IsNull()) { - if (playbackPosition.Value().position.IsNull()) { - objCPlaybackPosition = [[MediaPlayback_PlaybackPosition alloc] - initWithUpdatedAt:@(playbackPosition.Value().updatedAt) - position:nil]; - } else { - objCPlaybackPosition = [[MediaPlayback_PlaybackPosition alloc] - initWithUpdatedAt:@(playbackPosition.Value().updatedAt) - position:@(playbackPosition.Value().position.Value())]; - } - callback(objCPlaybackPosition); - } - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeSampledPosition"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeSampledPosition"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribePlaybackSpeed:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(float))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().mediaPlayback_subscribePlaybackSpeed() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribePlaybackSpeed"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribePlaybackSpeed"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribePlaybackSpeed"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribePlaybackSpeed(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToPlaybackSpeed( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::PlaybackSpeed::TypeInfo::DecodableArgType - playbackSpeed) { - void (^callback)(float) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribePlaybackSpeed"]; - callback(playbackSpeed); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribePlaybackSpeed"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribePlaybackSpeed"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribeSeekRangeEnd:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().mediaPlayback_subscribeSeekRangeEnd() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeSeekRangeEnd(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToDuration( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::TypeInfo::DecodableArgType - seekRangeEnd) { - void (^callback)(NSNumber * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - callback(@(seekRangeEnd.Value())); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeEnd"]; - callback(); - }); - - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)mediaPlayback_subscribeSeekRangeStart:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nullable))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().mediaPlayback_subscribeSeekRangeStart() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"mediaPlayback_subscribeSeekRangeStart"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"mediaPlayback_subscribeSeekRangeStart"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"mediaPlayback_subscribeSeekRangeStart"]; - - [self - dispatchOnMatterSDKQueue:@"mediaPlayback_subscribeSeekRangeStart(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->MediaPlayback_SubscribeToDuration( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::TypeInfo::DecodableArgType - seekRangeStart) { - void (^callback)(NSNumber * _Nullable) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeStart"]; - callback(@(seekRangeStart.Value())); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeStart"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"mediaPlayback_subscribeSeekRangeStart"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationLauncher_launchApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - data:(NSData * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - - chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::Type application; - application.catalogVendorID = catalogVendorId; - application.applicationID = chip::CharSpan::fromCharString([applicationId UTF8String]); - - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->ApplicationLauncher_LaunchApp(&endpoint, application, - chip::MakeOptional(chip::ByteSpan(static_cast(data.bytes), data.length)), - responseFunction); - }]; -} - -- (void)applicationLauncher_stopApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::Type application; - application.catalogVendorID = catalogVendorId; - application.applicationID = chip::CharSpan::fromCharString([applicationId UTF8String]); - - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->ApplicationLauncher_StopApp(&endpoint, application, responseFunction); - }]; -} - -- (void)applicationLauncher_hideApp:(ContentApp * _Nonnull)contentApp - catalogVendorId:(uint16_t)catalogVendorId - applicationId:(NSString * _Nonnull)applicationId - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - - chip::app::Clusters::ApplicationLauncher::Structs::ApplicationStruct::Type application; - application.catalogVendorID = catalogVendorId; - application.applicationID = chip::CharSpan::fromCharString([applicationId UTF8String]); - - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->ApplicationLauncher_HideApp(&endpoint, application, responseFunction); - }]; -} - -- (void)targetNavigator_navigateTarget:(ContentApp * _Nonnull)contentApp - target:(uint8_t)target - data:(NSString * _Nullable)data - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->TargetNavigator_NavigateTarget(&endpoint, target, - chip::MakeOptional(chip::CharSpan::fromCharString([data UTF8String])), responseFunction); - }]; -} - -- (void)targetNavigator_subscribeTargetList:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSMutableArray *))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().targetNavigator_subscribeTargetList() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"targetNavigator_subscribeTargetList"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"targetNavigator_subscribeTargetList"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"targetNavigator_subscribeTargetList"]; - - [self - dispatchOnMatterSDKQueue:@"targetNavigator_subscribeTargetList(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->TargetNavigator_SubscribeToTargetList( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::TargetNavigator::Attributes::TargetList::TypeInfo::DecodableArgType - targetList) { - void (^callback)(NSMutableArray *) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"targetNavigator_subscribeTargetList"]; - NSMutableArray * objCTargetList = nil; - size_t targetInfoCount; - targetList.ComputeSize(&targetInfoCount); - if (targetInfoCount > 0) { - objCTargetList = [NSMutableArray arrayWithCapacity:targetInfoCount]; - auto iter = targetList.begin(); - while (iter.Next()) { - const chip::app::Clusters::TargetNavigator::Structs::TargetInfoStruct:: - DecodableType & targetInfo - = iter.GetValue(); - TargetNavigator_TargetInfoStruct * objCTargetInfoStruct = - [[TargetNavigator_TargetInfoStruct alloc] - initWithIdentifier:@(targetInfo.identifier) - name:[NSString stringWithUTF8String:targetInfo.name.data()]]; - [objCTargetList addObject:objCTargetInfoStruct]; - } - } - callback(objCTargetList); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"targetNavigator_subscribeTargetList"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"targetNavigator_subscribeTargetList"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)targetNavigator_subscribeCurrentTarget:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint8_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().targetNavigator_subscribeCurrentTarget() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"targetNavigator_subscribeCurrentTarget"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"targetNavigator_subscribeCurrentTarget"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"targetNavigator_subscribeCurrentTarget"]; - - [self - dispatchOnMatterSDKQueue:@"targetNavigator_subscribeCurrentTarget(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->TargetNavigator_SubscribeToCurrentTarget( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::TargetNavigator::Attributes::CurrentTarget::TypeInfo::DecodableArgType - currentTarget) { - void (^callback)(uint8_t) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"targetNavigator_subscribeCurrentTarget"]; - callback(currentTarget); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"targetNavigator_subscribeCurrentTarget"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"targetNavigator_subscribeCurrentTarget"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)keypadInput_sendKey:(ContentApp * _Nonnull)contentApp - keyCode:(uint8_t)keyCode - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->KeypadInput_SendKey(&endpoint, - static_cast(keyCode), responseFunction); - }]; -} - -- (void)applicationBasic_subscribeVendorName:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_subscribeVendorName() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_subscribeVendorName"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_subscribeVendorName"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"applicationBasic_subscribeVendorName"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_subscribeVendorName(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_SubscribeToVendorName( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::VendorName::TypeInfo::DecodableArgType - vendorName) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"applicationBasic_subscribeVendorName"]; - callback(vendorName.data() != nil ? [NSString stringWithUTF8String:vendorName.data()] : nil); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"applicationBasic_subscribeVendorName"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"applicationBasic_subscribeVendorName"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_subscribeVendorID:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_subscribeVendorID() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_subscribeVendorID"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_subscribeVendorID"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"applicationBasic_subscribeVendorID"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_subscribeVendorID(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_SubscribeToVendorID( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo::DecodableArgType - vendorID) { - void (^callback)(NSNumber * _Nonnull) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"applicationBasic_subscribeVendorID"]; - callback(@(vendorID)); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"applicationBasic_subscribeVendorID"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"applicationBasic_subscribeVendorID"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_subscribeApplicationName:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_subscribeApplicationName() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_subscribeApplicationName"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_subscribeApplicationName"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback - forKey:@"applicationBasic_subscribeApplicationName"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_subscribeApplicationName(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_SubscribeToApplicationName( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ApplicationName::TypeInfo:: - DecodableArgType applicationName) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"applicationBasic_subscribeApplicationName"]; - callback([NSString stringWithUTF8String:applicationName.data()]); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"applicationBasic_subscribeApplicationName"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"applicationBasic_subscribeApplicationName"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_subscribeProductID:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint16_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_subscribeProductID() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_subscribeProductID"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_subscribeProductID"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback forKey:@"applicationBasic_subscribeProductID"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_subscribeProductID(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_SubscribeToProductID( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ProductID::TypeInfo::DecodableArgType - productID) { - void (^callback)(uint16_t) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"applicationBasic_subscribeProductID"]; - callback(productID); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"applicationBasic_subscribeProductID"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"applicationBasic_subscribeProductID"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_subscribeApplicationVersion:(ContentApp * _Nonnull)contentApp - minInterval:(uint16_t)minInterval - maxInterval:(uint16_t)maxInterval - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback - subscriptionEstablishedCallback:(void (^_Nonnull)())subscriptionEstablishedCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_subscribeApplicationVersion() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_subscriptionReadSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_subscribeApplicationVersion"]; - [_subscriptionReadFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_subscribeApplicationVersion"]; - [_subscriptionEstablishedCallbacks setObject:subscriptionEstablishedCallback - forKey:@"applicationBasic_subscribeApplicationVersion"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_subscribeApplicationVersion(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_SubscribeToApplicationVersion( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ApplicationVersion::TypeInfo:: - DecodableArgType applicationVersion) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].subscriptionReadSuccessCallbacks - objectForKey:@"applicationBasic_subscribeApplicationVersion"]; - callback([NSString stringWithUTF8String:applicationVersion.data()]); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].subscriptionReadFailureCallbacks - objectForKey:@"applicationBasic_subscribeApplicationVersion"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }, - minInterval, maxInterval, - [](void * context, chip::SubscriptionId subscriptionId) { - void (^callback)() = - [[CastingServerBridge getSharedInstance].subscriptionEstablishedCallbacks - objectForKey:@"applicationBasic_subscribeApplicationVersion"]; - callback(); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_readVendorName:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readVendorName() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_readSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_readVendorName"]; - [_readFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_readVendorName"]; - - [self - dispatchOnMatterSDKQueue:[NSString stringWithFormat:@"%s(...)", __func__] - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_ReadVendorName( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::VendorName::TypeInfo::DecodableArgType - vendorName) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].readSuccessCallbacks - objectForKey:@"applicationBasic_readVendorName"]; - callback([NSString stringWithUTF8String:vendorName.data()]); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].readFailureCallbacks - objectForKey:@"applicationBasic_readVendorName"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_readVendorID:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSNumber * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readVendorID() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_readSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_readVendorID"]; - [_readFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_readVendorID"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_readVendorID(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_ReadVendorID( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::VendorID::TypeInfo::DecodableArgType - vendorID) { - void (^callback)(NSNumber * _Nonnull) = - [[CastingServerBridge getSharedInstance].readSuccessCallbacks - objectForKey:@"applicationBasic_readVendorID"]; - callback(@(vendorID)); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].readFailureCallbacks - objectForKey:@"applicationBasic_readVendorID"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_readApplicationName:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_readApplicationName() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_readSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_readApplicationName"]; - [_readFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_readApplicationName"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_readApplicationName(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_ReadApplicationName( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ApplicationName::TypeInfo:: - DecodableArgType applicationName) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].readSuccessCallbacks - objectForKey:@"applicationBasic_readApplicationName"]; - callback([NSString stringWithUTF8String:applicationName.data()]); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].readFailureCallbacks - objectForKey:@"applicationBasic_readApplicationName"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_readProductID:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(uint16_t))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback -{ - ChipLogProgress(AppServer, "CastingServerBridge().applicationBasic_readProductID() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_readSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_readProductID"]; - [_readFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_readProductID"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_readProductID(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_ReadProductID( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ProductID::TypeInfo::DecodableArgType - productID) { - void (^callback)(uint16_t) = [[CastingServerBridge getSharedInstance].readSuccessCallbacks - objectForKey:@"applicationBasic_readProductID"]; - callback(productID); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].readFailureCallbacks - objectForKey:@"applicationBasic_readProductID"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)applicationBasic_readApplicationVersion:(ContentApp * _Nonnull)contentApp - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(MatterError * _Nonnull))requestSentHandler - successCallback:(void (^_Nonnull)(NSString * _Nonnull))successCallback - failureCallback:(void (^_Nonnull)(MatterError * _Nonnull))failureCallback -{ - ChipLogProgress(AppServer, - "CastingServerBridge().applicationBasic_readApplicationVersion() called on Content App with endpoint ID %d", - contentApp.endpointId); - - [_readSuccessCallbacks setObject:successCallback forKey:@"applicationBasic_readApplicationVersion"]; - [_readFailureCallbacks setObject:failureCallback forKey:@"applicationBasic_readApplicationVersion"]; - - [self - dispatchOnMatterSDKQueue:@"applicationBasic_readApplicationVersion(...)" - block:^{ - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - CHIP_ERROR err = CastingServer::GetInstance()->ApplicationBasic_ReadApplicationVersion( - &endpoint, nullptr, - [](void * context, - chip::app::Clusters::ApplicationBasic::Attributes::ApplicationVersion::TypeInfo:: - DecodableArgType applicationVersion) { - void (^callback)(NSString * _Nonnull) = - [[CastingServerBridge getSharedInstance].readSuccessCallbacks - objectForKey:@"applicationBasic_readApplicationVersion"]; - callback([NSString stringWithUTF8String:applicationVersion.data()]); - }, - [](void * context, CHIP_ERROR err) { - void (^callback)(MatterError *) = - [[CastingServerBridge getSharedInstance].readFailureCallbacks - objectForKey:@"applicationBasic_readApplicationVersion"]; - callback([[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - dispatch_async(clientQueue, ^{ - requestSentHandler( - [[MatterError alloc] initWithCode:err.AsInteger() - message:[NSString stringWithUTF8String:err.AsString()]]); - }); - }]; -} - -- (void)onOff_on:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->OnOff_On(&endpoint, responseFunction); - }]; -} - -- (void)onOff_off:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->OnOff_Off(&endpoint, responseFunction); - }]; -} - -- (void)onOff_toggle:(ContentApp * _Nonnull)contentApp - responseCallback:(void (^_Nonnull)(bool))responseCallback - clientQueue:(dispatch_queue_t _Nonnull)clientQueue - requestSentHandler:(void (^_Nonnull)(bool))requestSentHandler -{ - const NSString * description = [NSString stringWithFormat:@"%s(...) (Content App %d)", __func__, contentApp.endpointId]; - [self withCastingServerInvokeBlock:description - callbackQueue:clientQueue - onBlockComplete:requestSentHandler - onResponse:responseCallback - block:^(CastingServer * castingServer, std::function responseFunction) { - TargetEndpointInfo endpoint; - [ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:endpoint]; - - return castingServer->OnOff_Toggle(&endpoint, responseFunction); - }]; -} -@end diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h deleted file mode 100644 index 8f55e33e27402a..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/CommissionerDiscoveryDelegateImpl.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * - * Copyright (c) 2022 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. - */ - -#ifndef CommissionerDiscoveryDelegateImpl_h -#define CommissionerDiscoveryDelegateImpl_h - -#import "ConversionUtils.hpp" -#include -#include - -class CommissionerDiscoveryDelegateImpl : public chip::Controller::DeviceDiscoveryDelegate { -public: - void SetUp(dispatch_queue_t _Nonnull clientQueue, - void (^_Nonnull objCDiscoveredCommissionerHandler)(DiscoveredNodeData * _Nonnull), - TargetVideoPlayerInfo * _Nullable cachedTargetVideoPlayerInfos) - { - mClientQueue = clientQueue; - mObjCDiscoveredCommissionerHandler = objCDiscoveredCommissionerHandler; - mCachedTargetVideoPlayerInfos = cachedTargetVideoPlayerInfos; - mDiscoveredCommissioners.clear(); - - /** - * Surface players (as DiscoveredNodeData objects on discoverySuccessCallback) that we previously - * connected to and received their WakeOnLAN MACAddress, but could not discover over DNS-SD this time in - * CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC. This API will also ensure that the reported players - * were previously discoverable within CHIP_DEVICE_CONFIG_STR_CACHE_LAST_DISCOVERED_HOURS. - * - * The DiscoveredNodeData object for such players will have the IsAsleep attribute set to true, - * which can optionally be used for any special UX treatment when displaying them. - * - * Surfacing such players as discovered will allow displaying them to the user, who may want to - * cast to them. In such a case, the VerifyOrEstablishConnection API will turn them on over - * WakeOnLan. - */ - chip::DeviceLayer::SystemLayer().CancelTimer( - ReportSleepingCommissioners, this); // cancel preexisting timer for ReportSleepingCommissioners, if any - if (mCachedTargetVideoPlayerInfos != nullptr && mCachedTargetVideoPlayerInfos[0].IsInitialized()) { - chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32( -#ifdef CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC - CHIP_DEVICE_CONFIG_STR_DISCOVERY_DELAY_SEC -#else - 0 -#endif - * 1000), - ReportSleepingCommissioners, this); - } - } - - void OnDiscoveredDevice(const chip::Dnssd::CommissionNodeData & nodeData) - { - ChipLogProgress(AppServer, "CommissionerDiscoveryDelegateImpl().OnDiscoveredDevice() called"); - __block const chip::Dnssd::CommissionNodeData cppNodeData = nodeData; - dispatch_async(mClientQueue, ^{ - DiscoveredNodeData * objCDiscoveredNodeData = [ConversionUtils convertToObjCDiscoveredNodeDataFrom:&cppNodeData]; - mDiscoveredCommissioners.push_back(objCDiscoveredNodeData); // add to the list of discovered commissioners - - // set associated connectable video player from cache, if any - if (mCachedTargetVideoPlayerInfos != nullptr) { - for (size_t i = 0; i < kMaxCachedVideoPlayers && mCachedTargetVideoPlayerInfos[i].IsInitialized(); i++) { - if (mCachedTargetVideoPlayerInfos[i].IsSameAs(&cppNodeData)) { - chip::System::Clock::Timestamp currentUnixTimeMS = chip::System::Clock::kZero; - chip::System::SystemClock().GetClock_RealTimeMS(currentUnixTimeMS); - ChipLogProgress(AppServer, "Updating discovery timestamp for VideoPlayer %lu", - static_cast(currentUnixTimeMS.count())); - mCachedTargetVideoPlayerInfos[i].SetLastDiscovered(currentUnixTimeMS); // add discovery timestamp - CastingServer::GetInstance()->AddVideoPlayer( - &mCachedTargetVideoPlayerInfos[i]); // write updated video player to cache - - VideoPlayer * connectableVideoPlayer = - [ConversionUtils convertToObjCVideoPlayerFrom:&mCachedTargetVideoPlayerInfos[i]]; - [objCDiscoveredNodeData setConnectableVideoPlayer:connectableVideoPlayer]; - } - } - } - - // make the callback - mObjCDiscoveredCommissionerHandler(objCDiscoveredNodeData); - }); - } - -private: - static void ReportSleepingCommissioners(chip::System::Layer * _Nonnull aSystemLayer, void * _Nullable context) - { - ChipLogProgress(AppServer, "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() called"); - CommissionerDiscoveryDelegateImpl * thiz = (CommissionerDiscoveryDelegateImpl *) context; - if (thiz == nullptr || thiz->mCachedTargetVideoPlayerInfos == nullptr) { - ChipLogProgress( - AppServer, "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() found no cached video players"); - return; - } - for (size_t i = 0; i < kMaxCachedVideoPlayers && thiz->mCachedTargetVideoPlayerInfos[i].IsInitialized(); i++) { - // do NOT surface this cached Player if we don't have its MACAddress - if (thiz->mCachedTargetVideoPlayerInfos[i].GetMACAddress() == nullptr - && thiz->mCachedTargetVideoPlayerInfos[i].GetMACAddress()->size() == 0) { - ChipLogProgress(NotSpecified, - "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() Skipping Player with hostName %s but no " - "MACAddress", - thiz->mCachedTargetVideoPlayerInfos[i].GetHostName()); - continue; - } - - // do NOT surface this cached Player if it has not been discoverable recently - if (!thiz->mCachedTargetVideoPlayerInfos[i].WasRecentlyDiscoverable()) { - ChipLogProgress(NotSpecified, - "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() Skipping Player with hostName %s that " - "has not been discovered recently", - thiz->mCachedTargetVideoPlayerInfos[i].GetHostName()); - continue; - } - - // do NOT surface this cached Player if it was just discovered right now (in this discovery call) - bool justDiscovered = false; - for (DiscoveredNodeData * discoveredCommissioner : thiz->mDiscoveredCommissioners) { - if (strcmp( - (char *) [discoveredCommissioner.hostName UTF8String], thiz->mCachedTargetVideoPlayerInfos[i].GetHostName()) - == 0) { - justDiscovered = true; - break; - } - } - if (justDiscovered) { - ChipLogProgress(NotSpecified, - "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() Skipping Player with hostName %s that " - "was just discovered", - thiz->mCachedTargetVideoPlayerInfos[i].GetHostName()); - continue; - } - - // DO surface this cached Player (as asleep) - DiscoveredNodeData * objCDiscoveredNodeData = - [ConversionUtils convertToDiscoveredNodeDataFrom:&thiz->mCachedTargetVideoPlayerInfos[i]]; - objCDiscoveredNodeData.getConnectableVideoPlayer.isAsleep = true; - ChipLogProgress(AppServer, "CommissionerDiscoveryDelegateImpl().ReportSleepingCommissioners() with hostName %s", - thiz->mCachedTargetVideoPlayerInfos[i].GetHostName()); - thiz->mObjCDiscoveredCommissionerHandler(objCDiscoveredNodeData); - } - } - - std::vector mDiscoveredCommissioners; - void (^_Nonnull mObjCDiscoveredCommissionerHandler)(DiscoveredNodeData * _Nonnull); - dispatch_queue_t _Nonnull mClientQueue; - TargetVideoPlayerInfo * _Nullable mCachedTargetVideoPlayerInfos; -}; - -#endif /* CommissionerDiscoveryDelegateImpl_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.hpp b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.hpp deleted file mode 100644 index 597b3728e3f6c5..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/** - * - * Copyright (c) 2020-2022 Project CHIP Authors - * - * 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. - */ - -#import - -#import "AppParameters.h" -#import "ContentApp.h" -#import "DiscoveredNodeData.h" -#import "VideoPlayer.h" - -#import -#import -#import -#include - -#ifndef ConversionUtils_h -#define ConversionUtils_h - -@interface ConversionUtils : NSObject -/** - * @brief Objective C to C++ converters - */ -+ (CHIP_ERROR)convertToCppAppParamsInfoFrom:(AppParameters * _Nonnull)objCAppParameters outAppParams:(AppParams &)outAppParams; - -+ (CHIP_ERROR)convertToCppTargetEndpointInfoFrom:(ContentApp * _Nonnull)objCContentApp - outTargetEndpointInfo:(TargetEndpointInfo &)outTargetEndpointInfo; - -+ (CHIP_ERROR)convertToCppTargetVideoPlayerInfoFrom:(VideoPlayer * _Nonnull)objCVideoPlayer - outTargetVideoPlayerInfo:(TargetVideoPlayerInfo &)outTargetVideoPlayerInfo; - -+ (CHIP_ERROR)convertToCppDiscoveredNodeDataFrom:(DiscoveredNodeData * _Nonnull)objCDiscoveredNodeData - outDiscoveredNodeData:(chip::Dnssd::CommissionNodeData &)outDiscoveredNodeData; - -/** - * @brief C++ to Objective C converters - */ -+ (ContentApp * _Nonnull)convertToObjCContentAppFrom:(TargetEndpointInfo * _Nonnull)cppTargetEndpointInfo; - -+ (DiscoveredNodeData * _Nonnull)convertToObjCDiscoveredNodeDataFrom: - (const chip::Dnssd::CommissionNodeData * _Nonnull)cppDiscoveredNodedata; - -+ (VideoPlayer * _Nonnull)convertToObjCVideoPlayerFrom:(TargetVideoPlayerInfo * _Nonnull)cppTargetVideoPlayerInfo; - -/** - * @brief inter-object converters - */ -+ (DiscoveredNodeData * _Nonnull)convertToDiscoveredNodeDataFrom:(TargetVideoPlayerInfo * _Nonnull)cppTargetVideoPlayerInfo; - -@end - -#endif /* ConversionUtils_h */ diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm deleted file mode 100644 index 5cce096756bfa0..00000000000000 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/ConversionUtils.mm +++ /dev/null @@ -1,218 +0,0 @@ -/** - * - * Copyright (c) 2020-2023 Project CHIP Authors - * - * 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. - */ -#import - -#import "ConversionUtils.hpp" - -@implementation ConversionUtils - -+ (CHIP_ERROR)convertToCppAppParamsInfoFrom:(AppParameters * _Nonnull)objCAppParameters outAppParams:(AppParams &)outAppParams -{ - VerifyOrReturnError(objCAppParameters != nil, CHIP_ERROR_INVALID_ARGUMENT); - - if (objCAppParameters.rotatingDeviceIdUniqueId != nil) { - chip::ByteSpan rotatingDeviceIdUniqueId - = chip::ByteSpan(static_cast(objCAppParameters.rotatingDeviceIdUniqueId.bytes), - objCAppParameters.rotatingDeviceIdUniqueId.length); - outAppParams.SetRotatingDeviceIdUniqueId(MakeOptional(rotatingDeviceIdUniqueId)); - } - return CHIP_NO_ERROR; -} - -+ (CHIP_ERROR)convertToCppTargetEndpointInfoFrom:(ContentApp * _Nonnull)objCContentApp - outTargetEndpointInfo:(TargetEndpointInfo &)outTargetEndpointInfo -{ - VerifyOrReturnError(objCContentApp.isInitialized, CHIP_ERROR_INVALID_ARGUMENT); - outTargetEndpointInfo.Initialize(objCContentApp.endpointId); - for (NSNumber * clusterId in objCContentApp.clusterIds) { - VerifyOrReturnError(outTargetEndpointInfo.AddCluster([clusterId unsignedIntValue]), CHIP_ERROR_INVALID_ARGUMENT); - } - return CHIP_NO_ERROR; -} - -+ (CHIP_ERROR)convertToCppDiscoveredNodeDataFrom:(DiscoveredNodeData * _Nonnull)objCDiscoveredNodeData - outDiscoveredNodeData:(chip::Dnssd::CommissionNodeData &)outDiscoveredNodeData -{ - // setting CommissionNodeData - outDiscoveredNodeData.deviceType = objCDiscoveredNodeData.deviceType; - outDiscoveredNodeData.vendorId = objCDiscoveredNodeData.vendorId; - outDiscoveredNodeData.productId = objCDiscoveredNodeData.productId; - outDiscoveredNodeData.longDiscriminator = objCDiscoveredNodeData.longDiscriminator; - outDiscoveredNodeData.commissioningMode = objCDiscoveredNodeData.commissioningMode; - outDiscoveredNodeData.pairingHint = objCDiscoveredNodeData.pairingHint; - memset(outDiscoveredNodeData.deviceName, '\0', sizeof(outDiscoveredNodeData.deviceName)); - if (objCDiscoveredNodeData.deviceName != nullptr) { - chip::Platform::CopyString(outDiscoveredNodeData.deviceName, chip::Dnssd::kMaxDeviceNameLen + 1, - [objCDiscoveredNodeData.deviceName UTF8String]); - } - outDiscoveredNodeData.rotatingIdLen = objCDiscoveredNodeData.rotatingIdLen; - memcpy( - outDiscoveredNodeData.rotatingId, objCDiscoveredNodeData.rotatingId, objCDiscoveredNodeData.rotatingIdLen); - - // setting CommonResolutionData - outDiscoveredNodeData.port = objCDiscoveredNodeData.port; - memset(outDiscoveredNodeData.hostName, '\0', sizeof(outDiscoveredNodeData.hostName)); - if (objCDiscoveredNodeData.hostName != nullptr) { - chip::Platform::CopyString(outDiscoveredNodeData.hostName, chip::Dnssd::kHostNameMaxLength + 1, - [objCDiscoveredNodeData.hostName UTF8String]); - } - outDiscoveredNodeData.interfaceId = chip::Inet::InterfaceId(objCDiscoveredNodeData.platformInterface); - outDiscoveredNodeData.numIPs = objCDiscoveredNodeData.numIPs; - for (size_t i = 0; i < objCDiscoveredNodeData.numIPs; i++) { - chip::Inet::IPAddress::FromString( - [objCDiscoveredNodeData.ipAddresses[i] UTF8String], outDiscoveredNodeData.ipAddress[i]); - } - return CHIP_NO_ERROR; -} - -+ (CHIP_ERROR)convertToCppTargetVideoPlayerInfoFrom:(VideoPlayer * _Nonnull)objCVideoPlayer - outTargetVideoPlayerInfo:(TargetVideoPlayerInfo &)outTargetVideoPlayerInfo -{ - VerifyOrReturnError(objCVideoPlayer.isInitialized, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(outTargetVideoPlayerInfo.Initialize(objCVideoPlayer.nodeId, objCVideoPlayer.fabricIndex, nullptr, nullptr, - objCVideoPlayer.vendorId, objCVideoPlayer.productId, objCVideoPlayer.deviceType, [objCVideoPlayer.deviceName UTF8String], - [objCVideoPlayer.hostName UTF8String], 0, nullptr, objCVideoPlayer.port, [objCVideoPlayer.instanceName UTF8String], - chip::System::Clock::Timestamp(objCVideoPlayer.lastDiscoveredMs))); - if (objCVideoPlayer.MACAddress != nil) { - outTargetVideoPlayerInfo.SetMACAddress( - chip::CharSpan([objCVideoPlayer.MACAddress UTF8String], objCVideoPlayer.MACAddress.length)); - } - outTargetVideoPlayerInfo.SetIsAsleep(objCVideoPlayer.isAsleep); - - for (ContentApp * contentApp in objCVideoPlayer.contentApps) { - TargetEndpointInfo * endpoint = outTargetVideoPlayerInfo.GetOrAddEndpoint(contentApp.endpointId); - VerifyOrReturnError(endpoint != nullptr, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure([ConversionUtils convertToCppTargetEndpointInfoFrom:contentApp outTargetEndpointInfo:*endpoint]); - } - return CHIP_NO_ERROR; -} - -+ (ContentApp *)convertToObjCContentAppFrom:(TargetEndpointInfo * _Nonnull)cppTargetEndpointInfo -{ - ContentApp * objCContentApp = [ContentApp new]; - if (cppTargetEndpointInfo->IsInitialized()) { - objCContentApp.endpointId = cppTargetEndpointInfo->GetEndpointId(); - objCContentApp.clusterIds = [NSMutableArray new]; - chip::ClusterId * clusterIds = cppTargetEndpointInfo->GetClusters(); - for (size_t i = 0; i < kMaxNumberOfClustersPerEndpoint && clusterIds[i] != chip::kInvalidClusterId; i++) { - objCContentApp.clusterIds[i] = @(clusterIds[i]); - } - objCContentApp.isInitialized = true; - } - return objCContentApp; -} - -+ (DiscoveredNodeData *)convertToObjCDiscoveredNodeDataFrom:(const chip::Dnssd::CommissionNodeData * _Nonnull)cppDiscoveredNodedata -{ - DiscoveredNodeData * objCDiscoveredNodeData = [DiscoveredNodeData new]; - - // from CommissionNodeData - objCDiscoveredNodeData.deviceType = cppDiscoveredNodedata->deviceType; - objCDiscoveredNodeData.vendorId = cppDiscoveredNodedata->vendorId; - objCDiscoveredNodeData.productId = cppDiscoveredNodedata->productId; - objCDiscoveredNodeData.longDiscriminator = cppDiscoveredNodedata->longDiscriminator; - objCDiscoveredNodeData.commissioningMode = cppDiscoveredNodedata->commissioningMode; - objCDiscoveredNodeData.pairingHint = cppDiscoveredNodedata->pairingHint; - objCDiscoveredNodeData.deviceName = [NSString stringWithCString:cppDiscoveredNodedata->deviceName - encoding:NSUTF8StringEncoding]; - objCDiscoveredNodeData.rotatingIdLen = cppDiscoveredNodedata->rotatingIdLen; - objCDiscoveredNodeData.rotatingId = cppDiscoveredNodedata->rotatingId; - objCDiscoveredNodeData.instanceName = [NSString stringWithCString:cppDiscoveredNodedata->instanceName - encoding:NSUTF8StringEncoding]; - - // from CommonResolutionData - objCDiscoveredNodeData.port = cppDiscoveredNodedata->port; - objCDiscoveredNodeData.hostName = [NSString stringWithCString:cppDiscoveredNodedata->hostName - encoding:NSUTF8StringEncoding]; - objCDiscoveredNodeData.platformInterface = cppDiscoveredNodedata->interfaceId.GetPlatformInterface(); - objCDiscoveredNodeData.numIPs = cppDiscoveredNodedata->numIPs; - if (cppDiscoveredNodedata->numIPs > 0) { - objCDiscoveredNodeData.ipAddresses = [NSMutableArray new]; - } - for (size_t i = 0; i < cppDiscoveredNodedata->numIPs; i++) { - char addrCString[chip::Inet::IPAddress::kMaxStringLength]; - cppDiscoveredNodedata->ipAddress[i].ToString(addrCString, chip::Inet::IPAddress::kMaxStringLength); - objCDiscoveredNodeData.ipAddresses[i] = [NSString stringWithCString:addrCString encoding:NSASCIIStringEncoding]; - } - return objCDiscoveredNodeData; -} - -+ (DiscoveredNodeData *)convertToDiscoveredNodeDataFrom:(TargetVideoPlayerInfo * _Nonnull)cppTargetVideoPlayerInfo -{ - DiscoveredNodeData * objCDiscoveredNodeData = [DiscoveredNodeData new]; - - objCDiscoveredNodeData.deviceType = cppTargetVideoPlayerInfo->GetDeviceType(); - objCDiscoveredNodeData.vendorId = cppTargetVideoPlayerInfo->GetVendorId(); - objCDiscoveredNodeData.productId = cppTargetVideoPlayerInfo->GetProductId(); - objCDiscoveredNodeData.deviceName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetDeviceName() - encoding:NSUTF8StringEncoding]; - objCDiscoveredNodeData.instanceName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetInstanceName() - encoding:NSUTF8StringEncoding]; - - objCDiscoveredNodeData.port = cppTargetVideoPlayerInfo->GetPort(); - objCDiscoveredNodeData.hostName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetHostName() - encoding:NSUTF8StringEncoding]; - objCDiscoveredNodeData.numIPs = cppTargetVideoPlayerInfo->GetNumIPs(); - if (cppTargetVideoPlayerInfo->GetNumIPs() > 0) { - objCDiscoveredNodeData.ipAddresses = [NSMutableArray new]; - } - for (size_t i = 0; i < cppTargetVideoPlayerInfo->GetNumIPs(); i++) { - char addrCString[chip::Inet::IPAddress::kMaxStringLength]; - cppTargetVideoPlayerInfo->GetIpAddresses()[i].ToString(addrCString, chip::Inet::IPAddress::kMaxStringLength); - objCDiscoveredNodeData.ipAddresses[i] = [NSString stringWithCString:addrCString encoding:NSASCIIStringEncoding]; - } - - VideoPlayer * connectableVideoPlayer = [ConversionUtils convertToObjCVideoPlayerFrom:cppTargetVideoPlayerInfo]; - [objCDiscoveredNodeData setConnectableVideoPlayer:connectableVideoPlayer]; - return objCDiscoveredNodeData; -} - -+ (VideoPlayer *)convertToObjCVideoPlayerFrom:(TargetVideoPlayerInfo * _Nonnull)cppTargetVideoPlayerInfo -{ - VideoPlayer * objCVideoPlayer = [VideoPlayer new]; - if (cppTargetVideoPlayerInfo->IsInitialized()) { - objCVideoPlayer.nodeId = cppTargetVideoPlayerInfo->GetNodeId(); - objCVideoPlayer.fabricIndex = cppTargetVideoPlayerInfo->GetFabricIndex(); - objCVideoPlayer.vendorId = cppTargetVideoPlayerInfo->GetVendorId(); - objCVideoPlayer.productId = cppTargetVideoPlayerInfo->GetProductId(); - objCVideoPlayer.deviceType = cppTargetVideoPlayerInfo->GetDeviceType(); - objCVideoPlayer.isConnected = (cppTargetVideoPlayerInfo->GetOperationalDeviceProxy() != nil); - objCVideoPlayer.deviceName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetDeviceName() - encoding:NSUTF8StringEncoding]; - objCVideoPlayer.port = cppTargetVideoPlayerInfo->GetPort(); - if (cppTargetVideoPlayerInfo->GetMACAddress() != nullptr && cppTargetVideoPlayerInfo->GetMACAddress()->size() > 0) { - objCVideoPlayer.MACAddress = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetMACAddress()->data() - encoding:NSUTF8StringEncoding]; - } - objCVideoPlayer.isAsleep = cppTargetVideoPlayerInfo->IsAsleep(); - objCVideoPlayer.lastDiscoveredMs = cppTargetVideoPlayerInfo->GetLastDiscovered().count(); - objCVideoPlayer.instanceName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetInstanceName() - encoding:NSUTF8StringEncoding]; - objCVideoPlayer.hostName = [NSString stringWithCString:cppTargetVideoPlayerInfo->GetHostName() - encoding:NSUTF8StringEncoding]; - - objCVideoPlayer.contentApps = [NSMutableArray new]; - TargetEndpointInfo * cppTargetEndpointInfos = cppTargetVideoPlayerInfo->GetEndpoints(); - for (size_t i = 0; i < kMaxNumberOfEndpoints && cppTargetEndpointInfos[i].IsInitialized(); i++) { - objCVideoPlayer.contentApps[i] = [ConversionUtils convertToObjCContentAppFrom:&cppTargetEndpointInfos[i]]; - } - objCVideoPlayer.isInitialized = true; - } - return objCVideoPlayer; -} - -@end From b3087d6188926c3de5fb45d3cfdd2cd3b455bf70 Mon Sep 17 00:00:00 2001 From: Tennessee Carmel-Veilleux Date: Thu, 9 May 2024 14:56:53 -0400 Subject: [PATCH 27/39] Add build target for BRD2703A (#33362) * Add build target for BRD2703A Build-script-only change to allow building examples against EFR32 BRD2703A variant. Testing done: - `./scripts/build/build_examples.py --target efr32-brd2703a-unit-test build` works after this change, and not before. * Fix all targets golden file :( --------- Co-authored-by: Andrei Litvin --- scripts/build/build/targets.py | 1 + scripts/build/builders/efr32.py | 3 +++ scripts/build/testdata/all_targets_linux_x64.txt | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index aff2fac037d52b..ab0092d4dbc78e 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -230,6 +230,7 @@ def BuildEfr32Target(): # board target.AppendFixedTargets([ + TargetPart('brd2703a', board=Efr32Board.BRD2703A), TargetPart('brd4161a', board=Efr32Board.BRD4161A), TargetPart('brd4187c', board=Efr32Board.BRD4187C), TargetPart('brd4186c', board=Efr32Board.BRD4186C), diff --git a/scripts/build/builders/efr32.py b/scripts/build/builders/efr32.py index c2d685515b8219..1144cfc8c54a16 100644 --- a/scripts/build/builders/efr32.py +++ b/scripts/build/builders/efr32.py @@ -100,6 +100,7 @@ class Efr32Board(Enum): BRD4187C = 9 BRD4186C = 10 BRD4338A = 11 + BRD2703A = 12 def GnArgName(self): if self == Efr32Board.BRD4161A: @@ -124,6 +125,8 @@ def GnArgName(self): return 'BRD4187C' elif self == Efr32Board.BRD4338A: return 'BRD4338A' + elif self == Efr32Board.BRD2703A: + return 'BRD2703A' else: raise Exception('Unknown board #: %r' % self) diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index de45fdb9d8ba77..9c9fb464d33bd4 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -5,7 +5,7 @@ bouffalolab-{bl602-iot-matter-v1,bl602-night-light,xt-zb6-devkit,bl706-night-lig cc32xx-{lock,air-purifier} ti-cc13x4_26x4-{all-clusters,lighting,lock,pump,pump-controller}[-mtd][-ftd] cyw30739-{cyw30739b2_p5_evk_01,cyw30739b2_p5_evk_02,cyw30739b2_p5_evk_03,cyw930739m2evb_01,cyw930739m2evb_02}-{light,light-switch,lock,thermostat} -efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,brd4304a,brd4338a}-{window-covering,switch,unit-test,light,lock,thermostat,pump}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation] +efr32-{brd2703a,brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,brd4304a,brd4338a}-{window-covering,switch,unit-test,light,lock,thermostat,pump}[-rpc][-with-ota-requestor][-icd][-low-power][-shell][-no-logging][-openthread-mtd][-heap-monitoring][-no-openthread-cli][-show-qr-code][-wifi][-rs9116][-wf200][-siwx917][-ipv4][-additional-data-advertising][-use-ot-lib][-use-ot-coap-lib][-no-version][-skip-rps-generation] 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] genio-lighting-app linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-ossfuzz][-coverage][-dmalloc][-clang] From be9389ced25be6aa51398a9e3697dff113c5992e Mon Sep 17 00:00:00 2001 From: Vijay Selvaraj Date: Thu, 9 May 2024 15:05:38 -0400 Subject: [PATCH 28/39] Added an interface for revocation checks to DeviceAttestationVerifier (#31222) * Added an interface for revocation checks to DeviceAttestationVerifier * Addressed review comments * Removed the changes to add revocation set support to chip-tool and it will be submitted as a followup PR * Implemented PR #31222 review comments * Fixed issues in revocation check and code cleanup --- docs/ERROR_CODES.md | 1 + src/controller/AutoCommissioner.cpp | 9 +++ src/controller/CHIPDeviceController.cpp | 73 ++++++++++++++++++- src/controller/CHIPDeviceController.h | 10 +++ src/controller/CommissioningDelegate.cpp | 3 + src/controller/CommissioningDelegate.h | 2 + src/controller/python/OpCredsBinding.cpp | 2 + .../commissioning_failure_test.py | 4 +- .../DefaultDeviceAttestationVerifier.cpp | 10 +++ .../DefaultDeviceAttestationVerifier.h | 3 + .../DeviceAttestationVerifier.cpp | 8 ++ .../DeviceAttestationVerifier.h | 10 +++ src/lib/core/CHIPError.cpp | 3 + src/lib/core/CHIPError.h | 9 ++- src/lib/core/tests/TestCHIPErrorStr.cpp | 1 + src/python_testing/TC_CGEN_2_4.py | 6 +- 16 files changed, 144 insertions(+), 10 deletions(-) diff --git a/docs/ERROR_CODES.md b/docs/ERROR_CODES.md index ecfda40d943983..5799c7a3f1b885 100644 --- a/docs/ERROR_CODES.md +++ b/docs/ERROR_CODES.md @@ -47,6 +47,7 @@ This file was **AUTOMATICALLY** generated by | 29 | 0x1D | `CHIP_ERROR_INVALID_IPK` | | 30 | 0x1E | `CHIP_ERROR_INVALID_STRING_LENGTH` | | 31 | 0x1F | `CHIP_ERROR_INVALID_LIST_LENGTH` | +| 32 | 0x20 | `CHIP_ERROR_FAILED_DEVICE_ATTESTATION` | | 33 | 0x21 | `CHIP_ERROR_END_OF_TLV` | | 34 | 0x22 | `CHIP_ERROR_TLV_UNDERRUN` | | 35 | 0x23 | `CHIP_ERROR_INVALID_TLV_ELEMENT` | diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index a59ff82a551f1d..5b37988a491260 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -389,6 +389,8 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStageInternal(Commissio case CommissioningStage::kSendAttestationRequest: return CommissioningStage::kAttestationVerification; case CommissioningStage::kAttestationVerification: + return CommissioningStage::kAttestationRevocationCheck; + case CommissioningStage::kAttestationRevocationCheck: return CommissioningStage::kSendOpCertSigningRequest; case CommissioningStage::kSendOpCertSigningRequest: return CommissioningStage::kValidateCSR; @@ -693,6 +695,13 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio "Failed device attestation. Device vendor and/or product ID do not match the IDs expected. " "Verify DAC certificate chain and certification declaration to ensure spec rules followed."); } + + if (report.stageCompleted == CommissioningStage::kAttestationVerification) + { + ChipLogError(Controller, "Failed verifying attestation information. Now checking DAC chain revoked status."); + // don't error out until we check for DAC chain revocation status + err = CHIP_NO_ERROR; + } } else if (report.Is()) { diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index bb1143265945c2..910c0b21040c96 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -947,7 +947,7 @@ DeviceCommissioner::ContinueCommissioningAfterDeviceAttestation(DeviceProxy * de return CHIP_ERROR_INCORRECT_STATE; } - if (mCommissioningStage != CommissioningStage::kAttestationVerification) + if (mCommissioningStage != CommissioningStage::kAttestationRevocationCheck) { ChipLogError(Controller, "Commissioning is not attestation verification phase"); return CHIP_ERROR_INCORRECT_STATE; @@ -1175,6 +1175,17 @@ void DeviceCommissioner::OnDeviceAttestationInformationVerification( MATTER_TRACE_SCOPE("OnDeviceAttestationInformationVerification", "DeviceCommissioner"); DeviceCommissioner * commissioner = reinterpret_cast(context); + if (commissioner->mCommissioningStage == CommissioningStage::kAttestationVerification) + { + // Check for revoked DAC Chain before calling delegate. Enter next stage. + + CommissioningDelegate::CommissioningReport report; + report.Set(result); + + return commissioner->CommissioningStageComplete( + result == AttestationVerificationResult::kSuccess ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL, report); + } + if (!commissioner->mDeviceBeingCommissioned) { ChipLogError(Controller, "Device attestation verification result received when we're not commissioning a device"); @@ -1184,6 +1195,15 @@ void DeviceCommissioner::OnDeviceAttestationInformationVerification( auto & params = commissioner->mDefaultCommissioner->GetCommissioningParameters(); Credentials::DeviceAttestationDelegate * deviceAttestationDelegate = params.GetDeviceAttestationDelegate(); + if (params.GetCompletionStatus().attestationResult.HasValue()) + { + auto previousResult = params.GetCompletionStatus().attestationResult.Value(); + if (previousResult != AttestationVerificationResult::kSuccess) + { + result = previousResult; + } + } + if (result != AttestationVerificationResult::kSuccess) { CommissioningDelegate::CommissioningReport report; @@ -1398,6 +1418,18 @@ CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const Credentials::Device return CHIP_NO_ERROR; } +CHIP_ERROR +DeviceCommissioner::CheckForRevokedDACChain(const Credentials::DeviceAttestationVerifier::AttestationInfo & info) +{ + MATTER_TRACE_SCOPE("CheckForRevokedDACChain", "DeviceCommissioner"); + VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDeviceAttestationVerifier != nullptr, CHIP_ERROR_INCORRECT_STATE); + + mDeviceAttestationVerifier->CheckForRevokedDACChain(info, &mDeviceAttestationInformationVerificationCallback); + + return CHIP_NO_ERROR; +} + CHIP_ERROR DeviceCommissioner::ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements, const ByteSpan & AttestationSignature, const ByteSpan & dac, const ByteSpan & csrNonce) { @@ -3037,9 +3069,7 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio } case CommissioningStage::kAttestationVerification: { ChipLogProgress(Controller, "Verifying attestation"); - if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() || - !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() || - !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue()) + if (IsAttestationInformationMissing(params)) { ChipLogError(Controller, "Missing attestation information"); CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); @@ -3055,9 +3085,32 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio if (ValidateAttestationInfo(info) != CHIP_NO_ERROR) { ChipLogError(Controller, "Error validating attestation information"); + CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION); + return; + } + } + break; + case CommissioningStage::kAttestationRevocationCheck: { + ChipLogProgress(Controller, "Verifying device's DAC chain revocation status"); + if (IsAttestationInformationMissing(params)) + { + ChipLogError(Controller, "Missing attestation information"); CommissioningStageComplete(CHIP_ERROR_INVALID_ARGUMENT); return; } + + DeviceAttestationVerifier::AttestationInfo info( + params.GetAttestationElements().Value(), + proxy->GetSecureSession().Value()->AsSecureSession()->GetCryptoContext().GetAttestationChallenge(), + params.GetAttestationSignature().Value(), params.GetPAI().Value(), params.GetDAC().Value(), + params.GetAttestationNonce().Value(), params.GetRemoteVendorId().Value(), params.GetRemoteProductId().Value()); + + if (CheckForRevokedDACChain(info) != CHIP_NO_ERROR) + { + ChipLogError(Controller, "Error validating device's DAC chain revocation status"); + CommissioningStageComplete(CHIP_ERROR_FAILED_DEVICE_ATTESTATION); + return; + } } break; case CommissioningStage::kSendOpCertSigningRequest: { @@ -3424,6 +3477,18 @@ void DeviceCommissioner::ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, } } +bool DeviceCommissioner::IsAttestationInformationMissing(const CommissioningParameters & params) +{ + if (!params.GetAttestationElements().HasValue() || !params.GetAttestationSignature().HasValue() || + !params.GetAttestationNonce().HasValue() || !params.GetDAC().HasValue() || !params.GetPAI().HasValue() || + !params.GetRemoteVendorId().HasValue() || !params.GetRemoteProductId().HasValue()) + { + return true; + } + + return false; +} + CHIP_ERROR DeviceController::GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const { const auto * fabricInfo = GetFabricInfo(); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 42b8a7e2481541..8bef525e9cd773 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -1000,6 +1000,14 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, */ CHIP_ERROR ProcessCertificateChain(const ByteSpan & certificate); + /** + * @brief + * This function validates the revocation status of the DAC Chain sent by the device. + * + * @param[in] info Structure contatining all the required information for validating the device attestation. + */ + CHIP_ERROR CheckForRevokedDACChain(const Credentials::DeviceAttestationVerifier::AttestationInfo & info); + void HandleAttestationResult(CHIP_ERROR err); CommissioneeDeviceProxy * FindCommissioneeDevice(NodeId id); @@ -1053,6 +1061,8 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, // extend it). void ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params, CommissioningStage step); + bool IsAttestationInformationMissing(const CommissioningParameters & params); + chip::Callback::Callback mOnDeviceConnectedCallback; chip::Callback::Callback mOnDeviceConnectionFailureCallback; #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES diff --git a/src/controller/CommissioningDelegate.cpp b/src/controller/CommissioningDelegate.cpp index bbe82de18080d3..b3e3b6ca2ac754 100644 --- a/src/controller/CommissioningDelegate.cpp +++ b/src/controller/CommissioningDelegate.cpp @@ -70,6 +70,9 @@ const char * StageToString(CommissioningStage stage) case kAttestationVerification: return "AttestationVerification"; + case kAttestationRevocationCheck: + return "AttestationRevocationCheck"; + case kSendOpCertSigningRequest: return "SendOpCertSigningRequest"; diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index fae510b6b17325..e79ad1d67c4bcf 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -47,6 +47,7 @@ enum CommissioningStage : uint8_t kSendDACCertificateRequest, ///< Send DAC CertificateChainRequest (0x3E:2) command to the device kSendAttestationRequest, ///< Send AttestationRequest (0x3E:0) command to the device kAttestationVerification, ///< Verify AttestationResponse (0x3E:1) validity + kAttestationRevocationCheck, ///< Verify Revocation Status of device's DAC chain kSendOpCertSigningRequest, ///< Send CSRRequest (0x3E:4) command to the device kValidateCSR, ///< Verify CSRResponse (0x3E:5) validity kGenerateNOCChain, ///< TLV encode Node Operational Credentials (NOC) chain certs @@ -782,6 +783,7 @@ class CommissioningDelegate * kSendDACCertificateRequest: RequestedCertificate * kSendAttestationRequest: AttestationResponse * kAttestationVerification: AttestationErrorInfo if there is an error + * kAttestationRevocationCheck: AttestationErrorInfo if there is an error * kSendOpCertSigningRequest: CSRResponse * kGenerateNOCChain: NocChain * kSendTrustedRootCert: None diff --git a/src/controller/python/OpCredsBinding.cpp b/src/controller/python/OpCredsBinding.cpp index 66a6c841843cde..5fd4205d4c7ce7 100644 --- a/src/controller/python/OpCredsBinding.cpp +++ b/src/controller/python/OpCredsBinding.cpp @@ -331,6 +331,8 @@ class TestCommissioner : public chip::Controller::AutoCommissioner return mNeedsDST && mParams.GetDSTOffsets().HasValue(); case chip::Controller::CommissioningStage::kError: case chip::Controller::CommissioningStage::kSecurePairing: + // "not valid" because attestation verification always fails after entering revocation check step + case chip::Controller::CommissioningStage::kAttestationVerification: return false; default: return true; diff --git a/src/controller/python/test/test_scripts/commissioning_failure_test.py b/src/controller/python/test/test_scripts/commissioning_failure_test.py index 4681dd108d758a..eca170601c7f29 100755 --- a/src/controller/python/test/test_scripts/commissioning_failure_test.py +++ b/src/controller/python/test/test_scripts/commissioning_failure_test.py @@ -96,7 +96,7 @@ def main(): # TODO: Start at stage 2 once handling for arming failsafe on pase is done. if options.report: - for testFailureStage in range(3, 20): + for testFailureStage in range(3, 21): FailIfNot(test.TestPaseOnly(ip=options.deviceAddress1, setuppin=20202021, nodeid=1), @@ -105,7 +105,7 @@ def main(): "Commissioning failure tests failed for simulated report failure on stage {}".format(testFailureStage)) else: - for testFailureStage in range(3, 20): + for testFailureStage in range(3, 21): FailIfNot(test.TestPaseOnly(ip=options.deviceAddress1, setuppin=20202021, nodeid=1), diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp index 0d7f67ff82b0f6..f3444b0c303940 100644 --- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp +++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.cpp @@ -607,6 +607,16 @@ CHIP_ERROR DefaultDACVerifier::VerifyNodeOperationalCSRInformation(const ByteSpa return CHIP_NO_ERROR; } +void DefaultDACVerifier::CheckForRevokedDACChain(const AttestationInfo & info, + Callback::Callback * onCompletion) +{ + AttestationVerificationResult attestationError = AttestationVerificationResult::kSuccess; + + // TODO(#33124): Implement default version of CheckForRevokedDACChain + + onCompletion->mCall(onCompletion->mContext, info, attestationError); +} + bool CsaCdKeysTrustStore::IsCdTestKey(const ByteSpan & kid) const { return kid.data_equal(ByteSpan{ gTestCdPubkeyKid }); diff --git a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h index bdf7f705dbd0f1..346d098a58a337 100644 --- a/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h +++ b/src/credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h @@ -74,6 +74,9 @@ class DefaultDACVerifier : public DeviceAttestationVerifier const ByteSpan & attestationSignatureBuffer, const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) override; + void CheckForRevokedDACChain(const AttestationInfo & info, + Callback::Callback * onCompletion) override; + CsaCdKeysTrustStore * GetCertificationDeclarationTrustStore() override { return &mCdKeysTrustStore; } protected: diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp b/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp index cc5d9d3030de80..5bdbb9a8d82792 100644 --- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp +++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.cpp @@ -69,6 +69,14 @@ class UnimplementedDACVerifier : public DeviceAttestationVerifier (void) csrNonce; return CHIP_ERROR_NOT_IMPLEMENTED; } + + void CheckForRevokedDACChain(const AttestationInfo & info, + Callback::Callback * onCompletion) override + { + (void) info; + (void) onCompletion; + VerifyOrDie(false); + } }; // Default to avoid nullptr on getter and cleanly handle new products/clients before diff --git a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h index 9465d934207d1d..f45ceae06c23fe 100644 --- a/src/credentials/attestation_verifier/DeviceAttestationVerifier.h +++ b/src/credentials/attestation_verifier/DeviceAttestationVerifier.h @@ -386,6 +386,16 @@ class DeviceAttestationVerifier const Crypto::P256PublicKey & dacPublicKey, const ByteSpan & csrNonce) = 0; + /** + * @brief Verify whether or not the given DAC chain is revoked. + * + * @param[in] info All of the information required to check for revoked DAC chain. + * @param[in] onCompletion Callback handler to provide Attestation Information Verification result to the caller of + * CheckForRevokedDACChain() + */ + virtual void CheckForRevokedDACChain(const AttestationInfo & info, + Callback::Callback * onCompletion) = 0; + /** * @brief Get the trust store used for the attestation verifier. * diff --git a/src/lib/core/CHIPError.cpp b/src/lib/core/CHIPError.cpp index 68a44d8c39a7ea..2b2461ca79d09c 100644 --- a/src/lib/core/CHIPError.cpp +++ b/src/lib/core/CHIPError.cpp @@ -146,6 +146,9 @@ bool FormatCHIPError(char * buf, uint16_t bufSize, CHIP_ERROR err) case CHIP_ERROR_INVALID_LIST_LENGTH.AsInteger(): desc = "Invalid list length"; break; + case CHIP_ERROR_FAILED_DEVICE_ATTESTATION.AsInteger(): + desc = "Failed Device Attestation"; + break; case CHIP_END_OF_TLV.AsInteger(): desc = "End of TLV"; break; diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index 37001c8c6971a2..370a7d37d096ef 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -743,7 +743,14 @@ using CHIP_ERROR = ::chip::ChipError; */ #define CHIP_ERROR_INVALID_LIST_LENGTH CHIP_CORE_ERROR(0x1f) -// AVAILABLE: 0x20 +/** + * @def CHIP_ERROR_FAILED_DEVICE_ATTESTATION + * + * @brief + * Device Attestation failed. + * + */ +#define CHIP_ERROR_FAILED_DEVICE_ATTESTATION CHIP_CORE_ERROR(0x20) /** * @def CHIP_END_OF_TLV diff --git a/src/lib/core/tests/TestCHIPErrorStr.cpp b/src/lib/core/tests/TestCHIPErrorStr.cpp index 730a4843e14a45..54e187c72763fd 100644 --- a/src/lib/core/tests/TestCHIPErrorStr.cpp +++ b/src/lib/core/tests/TestCHIPErrorStr.cpp @@ -69,6 +69,7 @@ static const CHIP_ERROR kTestElements[] = CHIP_ERROR_UNINITIALIZED, CHIP_ERROR_INVALID_STRING_LENGTH, CHIP_ERROR_INVALID_LIST_LENGTH, + CHIP_ERROR_FAILED_DEVICE_ATTESTATION, CHIP_END_OF_TLV, CHIP_ERROR_TLV_UNDERRUN, CHIP_ERROR_INVALID_TLV_ELEMENT, diff --git a/src/python_testing/TC_CGEN_2_4.py b/src/python_testing/TC_CGEN_2_4.py index 23ab28ef09fad9..7bb2e6d21d3d73 100644 --- a/src/python_testing/TC_CGEN_2_4.py +++ b/src/python_testing/TC_CGEN_2_4.py @@ -34,9 +34,9 @@ kSendPAICertificateRequest = 10 kSendDACCertificateRequest = 11 kSendAttestationRequest = 12 -kSendOpCertSigningRequest = 14 -kSendTrustedRootCert = 17 -kSendNOC = 18 +kSendOpCertSigningRequest = 15 +kSendTrustedRootCert = 18 +kSendNOC = 19 class TC_CGEN_2_4(MatterBaseTest): From 7ea2832d6849d051b607ef7dbef476cc9ae353ec Mon Sep 17 00:00:00 2001 From: C Freeman Date: Thu, 9 May 2024 15:16:01 -0400 Subject: [PATCH 29/39] Python controller: add build option for ble (#33392) If you're just doing local dev, and don't have BLE, the controller take a long time attempting to initialize BLE before timing out. I'd rather not wait. --- scripts/build_python.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/build_python.sh b/scripts/build_python.sh index 87b567a7e5c256..f7db523ac4e175 100755 --- a/scripts/build_python.sh +++ b/scripts/build_python.sh @@ -37,6 +37,7 @@ echo_bold_white() { CHIP_ROOT=$(_normpath "$(dirname "$0")/..") OUTPUT_ROOT="$CHIP_ROOT/out/python_lib" +declare enable_ble=true declare chip_detail_logging=false declare enable_pybindings=false declare chip_mdns @@ -53,6 +54,7 @@ help() { echo "General Options: -h, --help Display this information. Input Options: + -b, --enable_ble Enable BLE in the controller (default=true) -d, --chip_detail_logging Specify ChipDetailLoggingValue as true or false. By default it is false. -m, --chip_mdns ChipMDNSValue Specify ChipMDNSValue as platform or minimal. @@ -82,6 +84,14 @@ while (($#)); do help exit 1 ;; + --enable_ble | -b) + enable_ble=$2 + if [[ "$enable_ble" != "true" && "$enable_ble" != "false" ]]; then + echo "chip_detail_logging should have a true/false value, not '$enable_ble'" + exit + fi + shift + ;; --chip_detail_logging | -d) chip_detail_logging=$2 if [[ "$chip_detail_logging" != "true" && "$chip_detail_logging" != "false" ]]; then @@ -147,7 +157,7 @@ while (($#)); do done # Print input values -echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\", enable_pybindings = $enable_pybindings, chip_case_retry_delta=\"$chip_case_retry_delta\", pregen_dir=\"$pregen_dir\"" +echo "Input values: chip_detail_logging = $chip_detail_logging , chip_mdns = \"$chip_mdns\", enable_pybindings = $enable_pybindings, chip_case_retry_delta=\"$chip_case_retry_delta\", pregen_dir=\"$pregen_dir\", enable_ble=\"$enable_ble\"" # Ensure we have a compilation environment source "$CHIP_ROOT/scripts/activate.sh" @@ -174,7 +184,7 @@ export SYSTEM_VERSION_COMPAT=0 # Make all possible human redable tracing available. tracing_options="matter_log_json_payload_hex=true matter_log_json_payload_decode_full=true matter_enable_tracing_support=true" -gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="$tracing_options chip_detail_logging=$chip_detail_logging enable_pylib=$enable_pybindings enable_rtti=$enable_pybindings chip_project_config_include_dirs=[\"//config/python\"] $chip_mdns_arg $chip_case_retry_arg $pregen_dir_arg" +gn --root="$CHIP_ROOT" gen "$OUTPUT_ROOT" --args="$tracing_options chip_detail_logging=$chip_detail_logging enable_pylib=$enable_pybindings enable_rtti=$enable_pybindings chip_project_config_include_dirs=[\"//config/python\"] $chip_mdns_arg $chip_case_retry_arg $pregen_dir_arg chip_config_network_layer_ble=$enable_ble chip_enable_ble=$enable_ble" function ninja_target() { # Print the ninja target required to build a gn label. From 048cf1216cfc69e1c0da090c75d1b34f6ef60807 Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Thu, 9 May 2024 15:23:31 -0400 Subject: [PATCH 30/39] [Silabs] Update matter support submodule pointer (#33374) * Update submodule pointer * Update file paths to pull matter support files * Fix offset calculation --- .../platform/silabs/SilabsDeviceAttestationCreds.cpp | 2 +- third_party/silabs/efr32_sdk.gni | 9 ++++++--- third_party/silabs/matter_support | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/platform/silabs/SilabsDeviceAttestationCreds.cpp b/examples/platform/silabs/SilabsDeviceAttestationCreds.cpp index 810529c26399ab..60785413070382 100644 --- a/examples/platform/silabs/SilabsDeviceAttestationCreds.cpp +++ b/examples/platform/silabs/SilabsDeviceAttestationCreds.cpp @@ -138,13 +138,13 @@ class DeviceAttestationCredsSilabs : public DeviceAttestationCredentialsProvider uint32_t size = size_default; ReturnErrorOnFailure(SilabsConfig::ReadConfigValue(SilabsConfig::kConfigKey_Creds_Base_Addr, base_addr)); - address = (uint8_t *) (base_addr + offset); // Offset if (SilabsConfig::ConfigValueExists(offset_key)) { ReturnErrorOnFailure(SilabsConfig::ReadConfigValue(offset_key, offset)); } + address = (uint8_t *) (base_addr + offset); // Size if (SilabsConfig::ConfigValueExists(size_key)) diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 5bb2ff3079fcc5..8b1ae3e7e6ff47 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -201,8 +201,6 @@ template("efr32_sdk") { "${efr32_sdk_root}/util/third_party/mbedtls/include/psa", "${efr32_sdk_root}/util/third_party/mbedtls/library", "${efr32_sdk_root}/platform/security/sl_component/sl_protocol_crypto/src", - "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/inc", - "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src", "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config/", "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/config/preset", "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/inc", @@ -214,6 +212,9 @@ template("efr32_sdk") { "${silabs_gen_folder}/config", "${silabs_gen_folder}/autogen", + # Use directory in matter support until gsdk files are updated + "${sdk_support_root}/platform/security/sl_component/sl_mbedtls_support/inc", + # Headers needed for Init no function will be called if OT is not used "${sl_ot_efr32_root}", ] @@ -684,7 +685,6 @@ template("efr32_sdk") { "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src/sl_entropy_hardware.c", "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src/sl_mbedtls.c", "${efr32_sdk_root}/platform/security/sl_component/sl_mbedtls_support/src/sli_psa_crypto.c", - "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sl_psa_its_nvm3.c", "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sli_psa_driver_common.c", "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sli_psa_driver_init.c", "${efr32_sdk_root}/platform/security/sl_component/sl_psa_driver/src/sli_psa_trng.c", @@ -783,6 +783,9 @@ template("efr32_sdk") { "${silabs_gen_folder}/autogen/sl_device_init_clocks.c", "${silabs_gen_folder}/autogen/sl_event_handler.c", "${silabs_gen_folder}/autogen/sl_iostream_handles.c", + + # Used file in matter_support until fix is pushed to gsdk + "${sdk_support_root}/platform/security/sl_component/sl_psa_driver/src/sl_psa_its_nvm3.c", ] if (enable_dic) { sources += [ diff --git a/third_party/silabs/matter_support b/third_party/silabs/matter_support index 56d4d4ec0dea03..edbfeba723c9ff 160000 --- a/third_party/silabs/matter_support +++ b/third_party/silabs/matter_support @@ -1 +1 @@ -Subproject commit 56d4d4ec0dea032302f52632c15d4d7813f8e9f5 +Subproject commit edbfeba723c9ffdc93f57ad1eee85186b1643f25 From 2ae320e61f0852f4c78a7a8dbf3b4204963b2cd8 Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Thu, 9 May 2024 16:01:52 -0400 Subject: [PATCH 31/39] [Silabs] Fix window-app sync issue with 917 soc (#33376) * Pull request #1812: [MATTER-2228] Remove all chip lock from the Lift and Tilt actions update. Merge in WMN_TOOLS/matter from fix/Window-app-synchronization to RC_2.3.0-1.3 Squashed commit of the following: commit 05e3e7224c6108e7e08ba4d9d7ff69f2b2c6fdc1 Author: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Tue May 7 16:30:30 2024 -0400 address last comments commit 2d32b0eca831de91ae1105cf076f07b7fd9d424f Author: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Tue May 7 15:02:16 2024 -0400 address comments commit 1db94351b7be41e9ef65cabafe1abf4910446848 Author: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Mon May 6 11:32:49 2024 -0400 Cleanup and add briefs and comments ... and 1 more commit * Restyled by clang-format * Apply suggestions and fix default config for the window app --------- Co-authored-by: Restyled.io --- .../window-app/silabs/build_for_wifi_args.gni | 1 + .../window-app/silabs/include/WindowManager.h | 71 +++--- examples/window-app/silabs/openthread.gni | 3 +- .../window-app/silabs/src/WindowManager.cpp | 219 ++++++++---------- 4 files changed, 135 insertions(+), 159 deletions(-) diff --git a/examples/window-app/silabs/build_for_wifi_args.gni b/examples/window-app/silabs/build_for_wifi_args.gni index afe39bf2604006..d6a8a54afbedb2 100644 --- a/examples/window-app/silabs/build_for_wifi_args.gni +++ b/examples/window-app/silabs/build_for_wifi_args.gni @@ -19,3 +19,4 @@ import("${chip_root}/src/platform/silabs/wifi_args.gni") chip_enable_ota_requestor = true app_data_model = "${chip_root}/examples/window-app/common:window-common" +sl_enable_test_event_trigger = true diff --git a/examples/window-app/silabs/include/WindowManager.h b/examples/window-app/silabs/include/WindowManager.h index 9faf6694238319..8ae75e8ed48c94 100644 --- a/examples/window-app/silabs/include/WindowManager.h +++ b/examples/window-app/silabs/include/WindowManager.h @@ -57,23 +57,33 @@ class WindowManager struct Cover { - void Init(chip::EndpointId endpoint); - - void LiftUpdate(bool newTarget); - void LiftGoToTarget() { LiftUpdate(true); } - void LiftContinueToTarget() { LiftUpdate(false); } - void LiftStepToward(OperationalState direction); - void LiftSchedulePositionSet(chip::Percent100ths position) { SchedulePositionSet(position, false); } - void LiftScheduleOperationalStateSet(OperationalState opState) { ScheduleOperationalStateSet(opState, false); } + enum ControlAction : uint8_t + { + Lift = 0, + Tilt = 1 + }; - void TiltUpdate(bool newTarget); - void TiltGoToTarget() { TiltUpdate(true); } - void TiltContinueToTarget() { TiltUpdate(false); } - void TiltStepToward(OperationalState direction); - void TiltSchedulePositionSet(chip::Percent100ths position) { SchedulePositionSet(position, true); } - void TiltScheduleOperationalStateSet(OperationalState opState) { ScheduleOperationalStateSet(opState, true); } + void Init(chip::EndpointId endpoint); - void UpdateTargetPosition(OperationalState direction, bool isTilt); + /** + * @brief Schedule a lift or a tilt related attribute transition on the ChipEvent queue + * **This function allocates a CoverWorkData which needs to be freed by the Worker callback** + * + * @param action : ControlAction::Lift will ScheduleWork LiftUpdateWorker, while ControlAction::Tilt will ScheduleWork + * TilitUpdateWorker + * @param setNewTarget : True will stop any ongoing transition and start a new one. False will continue the active + * transition updates + */ + void ScheduleControlAction(ControlAction action, bool setNewTarget); + // Helper functions that schedule Lift transitions + inline void LiftGoToTarget() { ScheduleControlAction(ControlAction::Lift, true); } + inline void LiftContinueToTarget() { ScheduleControlAction(ControlAction::Lift, false); } + // Helper functions that schedule Tilt transitions + inline void TiltGoToTarget() { ScheduleControlAction(ControlAction::Tilt, true); } + inline void TiltContinueToTarget() { ScheduleControlAction(ControlAction::Tilt, false); } + + void PositionSet(chip::EndpointId endpointId, chip::Percent100ths position, ControlAction action); + void UpdateTargetPosition(OperationalState direction, ControlAction action); Type CycleType(); @@ -88,22 +98,23 @@ class WindowManager OperationalState mLiftOpState = OperationalState::Stall; OperationalState mTiltOpState = OperationalState::Stall; - struct CoverWorkData - { - chip::EndpointId mEndpointId; - bool isTilt; - - union - { - chip::Percent100ths percent100ths; - OperationalState opState; - }; - }; + /** + * @brief Worker callbacks for the ScheduleControlAction. + * Those functions compute the operational state, and transititon movement based on the current and target positions + * for the cover. + * @param arg Context passed to the schedule worker. In this case, a CoverWorkData pointer + * The referenced CoverWorkData was allocated by ScheduleControlAction and must be freed by the worker. + */ + static void LiftUpdateWorker(intptr_t arg); + static void TiltUpdateWorker(intptr_t arg); + }; - void SchedulePositionSet(chip::Percent100ths position, bool isTilt); - static void CallbackPositionSet(intptr_t arg); - void ScheduleOperationalStateSet(OperationalState opState, bool isTilt); - static void CallbackOperationalStateSet(intptr_t arg); + struct CoverWorkData + { + Cover * cover = nullptr; + bool setNewTarget = false; + CoverWorkData(Cover * c, bool t) : cover(c), setNewTarget(t) {} + ~CoverWorkData() { cover = nullptr; } }; static WindowManager & Instance(); diff --git a/examples/window-app/silabs/openthread.gni b/examples/window-app/silabs/openthread.gni index 9fd09bd510a840..47c5860c9fb10d 100644 --- a/examples/window-app/silabs/openthread.gni +++ b/examples/window-app/silabs/openthread.gni @@ -21,13 +21,14 @@ silabs_sdk_target = get_label_info(":sdk", "label_no_toolchain") app_data_model = "${chip_root}/examples/window-app/common:window-common" chip_enable_ota_requestor = true chip_enable_openthread = true +sl_enable_test_event_trigger = true openthread_external_platform = "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32" # ICD Default configurations chip_enable_icd_server = true -enable_synchronized_sed = true +enable_synchronized_sed = false chip_subscription_timeout_resumption = false sl_use_subscription_syncing = true diff --git a/examples/window-app/silabs/src/WindowManager.cpp b/examples/window-app/silabs/src/WindowManager.cpp index af607fdbee7a64..0b8639dc04e93b 100644 --- a/examples/window-app/silabs/src/WindowManager.cpp +++ b/examples/window-app/silabs/src/WindowManager.cpp @@ -268,135 +268,131 @@ void WindowManager::Cover::Init(chip::EndpointId endpoint) chip::BitFlags safetyStatus(0x00); // 0 is no issues; } -void WindowManager::Cover::LiftStepToward(OperationalState direction) +void WindowManager::Cover::ScheduleControlAction(ControlAction action, bool setNewTarget) { - Protocols::InteractionModel::Status status; - chip::Percent100ths percent100ths; - NPercent100ths current; - - chip::DeviceLayer::PlatformMgr().LockChipStack(); - status = Attributes::CurrentPositionLiftPercent100ths::Get(mEndpoint, current); - chip::DeviceLayer::PlatformMgr().UnlockChipStack(); + VerifyOrReturn(action <= ControlAction::Tilt); + // Allocate a CoverWorkData. It will be freed by the Worker callback + CoverWorkData * data = new CoverWorkData(this, setNewTarget); + VerifyOrDie(data != nullptr); - if ((status == Protocols::InteractionModel::Status::Success) && !current.IsNull()) + AsyncWorkFunct workFunct = (action == ControlAction::Lift) ? LiftUpdateWorker : TiltUpdateWorker; + if (PlatformMgr().ScheduleWork(workFunct, reinterpret_cast(data)) != CHIP_NO_ERROR) { - percent100ths = ComputePercent100thsStep(direction, current.Value(), LIFT_DELTA); + ChipLogError(AppServer, "Failed to schedule cover control action"); + delete data; } - else - { - percent100ths = WC_PERCENT100THS_MIDDLE; // set at middle by default - } - - LiftSchedulePositionSet(percent100ths); } -void WindowManager::Cover::LiftUpdate(bool newTarget) +void WindowManager::Cover::LiftUpdateWorker(intptr_t arg) { - NPercent100ths current, target; + // Use a unique_prt so it's freed when leaving this context + std::unique_ptr data(reinterpret_cast(arg)); + Cover * cover = data->cover; - chip::DeviceLayer::PlatformMgr().LockChipStack(); + NPercent100ths current, target; - Attributes::TargetPositionLiftPercent100ths::Get(mEndpoint, target); - Attributes::CurrentPositionLiftPercent100ths::Get(mEndpoint, current); + VerifyOrReturn(Attributes::TargetPositionLiftPercent100ths::Get(cover->mEndpoint, target) == + Protocols::InteractionModel::Status::Success); + VerifyOrReturn(Attributes::CurrentPositionLiftPercent100ths::Get(cover->mEndpoint, current) == + Protocols::InteractionModel::Status::Success); OperationalState opState = ComputeOperationalState(target, current); - chip::DeviceLayer::PlatformMgr().UnlockChipStack(); - - /* If Triggered by a TARGET update */ - if (newTarget) + // If Triggered by a TARGET update + if (data->setNewTarget) { - mLiftTimer->Stop(); // Cancel previous motion if any - mLiftOpState = opState; + cover->mLiftTimer->Stop(); // Cancel previous motion if any + cover->mLiftOpState = opState; } - if (mLiftOpState == opState) + if (cover->mLiftOpState == opState) { - /* Actuator still need to move, not reached/crossed Target yet */ - LiftStepToward(mLiftOpState); + // Actuator still needs to move, has not reached/crossed Target yet + chip::Percent100ths percent100ths; + + if (!current.IsNull()) + { + percent100ths = ComputePercent100thsStep(cover->mLiftOpState, current.Value(), LIFT_DELTA); + } + else + { + percent100ths = WC_PERCENT100THS_MIDDLE; // set at middle by default + } + + cover->PositionSet(cover->mEndpoint, percent100ths, ControlAction::Lift); } - else /* CURRENT reached TARGET or crossed it */ + else // CURRENT reached TARGET or crossed it { - /* Actuator finalize the movement AND CURRENT Must be equal to TARGET at the end */ + // Actuator finalize the movement AND CURRENT Must be equal to TARGET at the end if (!target.IsNull()) - LiftSchedulePositionSet(target.Value()); + cover->PositionSet(cover->mEndpoint, target.Value(), ControlAction::Lift); - mLiftOpState = OperationalState::Stall; + cover->mLiftOpState = OperationalState::Stall; } - LiftScheduleOperationalStateSet(mLiftOpState); + OperationalStateSet(cover->mEndpoint, OperationalStatus::kLift, cover->mLiftOpState); - if ((OperationalState::Stall != mLiftOpState) && mLiftTimer) + if ((OperationalState::Stall != cover->mLiftOpState) && cover->mLiftTimer) { - mLiftTimer->Start(); + cover->mLiftTimer->Start(); } } -void WindowManager::Cover::TiltStepToward(OperationalState direction) +void WindowManager::Cover::TiltUpdateWorker(intptr_t arg) { - Protocols::InteractionModel::Status status; - chip::Percent100ths percent100ths; - NPercent100ths current; - - chip::DeviceLayer::PlatformMgr().LockChipStack(); - status = Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, current); - chip::DeviceLayer::PlatformMgr().UnlockChipStack(); - - if ((status == Protocols::InteractionModel::Status::Success) && !current.IsNull()) - { - percent100ths = ComputePercent100thsStep(direction, current.Value(), TILT_DELTA); - } - else - { - percent100ths = WC_PERCENT100THS_MIDDLE; // set at middle by default - } + // Use a unique_prt so it's freed when leaving this context + std::unique_ptr data(reinterpret_cast(arg)); + Cover * cover = data->cover; - TiltSchedulePositionSet(percent100ths); -} - -void WindowManager::Cover::TiltUpdate(bool newTarget) -{ NPercent100ths current, target; - - chip::DeviceLayer::PlatformMgr().LockChipStack(); - - Attributes::TargetPositionTiltPercent100ths::Get(mEndpoint, target); - Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, current); + VerifyOrReturn(Attributes::TargetPositionTiltPercent100ths::Get(cover->mEndpoint, target) == + Protocols::InteractionModel::Status::Success); + VerifyOrReturn(Attributes::CurrentPositionTiltPercent100ths::Get(cover->mEndpoint, current) == + Protocols::InteractionModel::Status::Success); OperationalState opState = ComputeOperationalState(target, current); - chip::DeviceLayer::PlatformMgr().UnlockChipStack(); - - /* If Triggered by a TARGET update */ - if (newTarget) + // If Triggered by a TARGET update + if (data->setNewTarget) { - mTiltTimer->Stop(); // Cancel previous motion if any - mTiltOpState = opState; + cover->mTiltTimer->Stop(); // Cancel previous motion if any + cover->mTiltOpState = opState; } - if (mTiltOpState == opState) + if (cover->mTiltOpState == opState) { - /* Actuator still need to move, not reached/crossed Target yet */ - TiltStepToward(mTiltOpState); + // Actuator still needs to move, has not reached/crossed Target yet + chip::Percent100ths percent100ths; + + if (!current.IsNull()) + { + percent100ths = ComputePercent100thsStep(cover->mTiltOpState, current.Value(), TILT_DELTA); + } + else + { + percent100ths = WC_PERCENT100THS_MIDDLE; // set at middle by default + } + + cover->PositionSet(cover->mEndpoint, percent100ths, ControlAction::Tilt); } - else /* CURRENT reached TARGET or crossed it */ + else // CURRENT reached TARGET or crossed it { - /* Actuator finalize the movement AND CURRENT Must be equal to TARGET at the end */ + // Actuator finalize the movement AND CURRENT Must be equal to TARGET at the end if (!target.IsNull()) - TiltSchedulePositionSet(target.Value()); + cover->PositionSet(cover->mEndpoint, target.Value(), ControlAction::Tilt); - mTiltOpState = OperationalState::Stall; + cover->mTiltOpState = OperationalState::Stall; } - TiltScheduleOperationalStateSet(mTiltOpState); + OperationalStateSet(cover->mEndpoint, OperationalStatus::kTilt, cover->mTiltOpState); - if ((OperationalState::Stall != mTiltOpState) && mTiltTimer) + if ((OperationalState::Stall != cover->mTiltOpState) && cover->mTiltTimer) { - mTiltTimer->Start(); + cover->mTiltTimer->Start(); } } -void WindowManager::Cover::UpdateTargetPosition(OperationalState direction, bool isTilt) +void WindowManager::Cover::UpdateTargetPosition(OperationalState direction, ControlAction action) { Protocols::InteractionModel::Status status; NPercent100ths current; @@ -404,7 +400,7 @@ void WindowManager::Cover::UpdateTargetPosition(OperationalState direction, bool chip::DeviceLayer::PlatformMgr().LockChipStack(); - if (isTilt) + if (action == ControlAction::Tilt) { status = Attributes::CurrentPositionTiltPercent100ths::Get(mEndpoint, current); if ((status == Protocols::InteractionModel::Status::Success) && !current.IsNull()) @@ -473,29 +469,15 @@ void WindowManager::Cover::OnTiltTimeout(WindowManager::Timer & timer) } } -void WindowManager::Cover::SchedulePositionSet(chip::Percent100ths position, bool isTilt) +void WindowManager::Cover::PositionSet(chip::EndpointId endpointId, chip::Percent100ths position, ControlAction action) { - CoverWorkData * data = chip::Platform::New(); - VerifyOrReturn(data != nullptr, ChipLogProgress(Zcl, "Cover::SchedulePositionSet - Out of Memory for WorkData")); - - data->mEndpointId = mEndpoint; - data->percent100ths = position; - data->isTilt = isTilt; - - chip::DeviceLayer::PlatformMgr().ScheduleWork(CallbackPositionSet, reinterpret_cast(data)); -} - -void WindowManager::Cover::CallbackPositionSet(intptr_t arg) -{ - NPercent100ths position; - WindowManager::Cover::CoverWorkData * data = reinterpret_cast(arg); - position.SetNonNull(data->percent100ths); - - if (data->isTilt) + NPercent100ths nullablePosition; + nullablePosition.SetNonNull(position); + if (action == ControlAction::Tilt) { - TiltPositionSet(data->mEndpointId, position); + TiltPositionSet(endpointId, nullablePosition); #ifdef DIC_ENABLE - uint16_t value = data->percent100ths; + uint16_t value = position; char buffer[MSG_SIZE]; itoa(value, buffer, DECIMAL); dic_sendmsg("tilt/position set", (const char *) (buffer)); @@ -503,36 +485,14 @@ void WindowManager::Cover::CallbackPositionSet(intptr_t arg) } else { - LiftPositionSet(data->mEndpointId, position); + LiftPositionSet(endpointId, nullablePosition); #ifdef DIC_ENABLE - uint16_t value = data->percent100ths; + uint16_t value = position; char buffer[MSG_SIZE]; itoa(value, buffer, DECIMAL); dic_sendmsg("lift/position set", (const char *) (buffer)); #endif // DIC_ENABLE } - chip::Platform::Delete(data); -} - -void WindowManager::Cover::ScheduleOperationalStateSet(OperationalState opState, bool isTilt) -{ - CoverWorkData * data = chip::Platform::New(); - VerifyOrReturn(data != nullptr, ChipLogProgress(Zcl, "Cover::OperationalStatusSet - Out of Memory for WorkData")); - - data->mEndpointId = mEndpoint; - data->opState = opState; - data->isTilt = isTilt; - - chip::DeviceLayer::PlatformMgr().ScheduleWork(CallbackOperationalStateSet, reinterpret_cast(data)); -} - -void WindowManager::Cover::CallbackOperationalStateSet(intptr_t arg) -{ - WindowManager::Cover::CoverWorkData * data = reinterpret_cast(arg); - - OperationalStateSet(data->mEndpointId, data->isTilt ? OperationalStatus::kTilt : OperationalStatus::kLift, data->opState); - - chip::Platform::Delete(data); } //------------------------------------------------------------------------------ @@ -756,7 +716,8 @@ void WindowManager::GeneralEventHandler(AppEvent * aEvent) } else { - window->GetCover().UpdateTargetPosition(OperationalState::MovingUpOrOpen, window->mTiltMode); + window->GetCover().UpdateTargetPosition( + OperationalState::MovingUpOrOpen, ((window->mTiltMode) ? Cover::ControlAction::Tilt : Cover::ControlAction::Lift)); } break; @@ -792,7 +753,9 @@ void WindowManager::GeneralEventHandler(AppEvent * aEvent) } else { - window->GetCover().UpdateTargetPosition(OperationalState::MovingDownOrClose, window->mTiltMode); + window->GetCover().UpdateTargetPosition( + OperationalState::MovingDownOrClose, + ((window->mTiltMode) ? Cover::ControlAction::Tilt : Cover::ControlAction::Lift)); } break; From 550b1c13608c2bbcbaca6e4375b19997cec4418b Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Thu, 9 May 2024 13:32:50 -0700 Subject: [PATCH 32/39] [Darwin] MTRDeviceConnectivityMonitor should weakify before using self in a handler block (#33395) --- .../CHIP/MTRDeviceConnectivityMonitor.mm | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceConnectivityMonitor.mm b/src/darwin/Framework/CHIP/MTRDeviceConnectivityMonitor.mm index 0d65304c843d04..229d95d9206bc1 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceConnectivityMonitor.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceConnectivityMonitor.mm @@ -148,19 +148,26 @@ - (void)handleResolvedHostname:(const char *)hostName port:(uint16_t)port error: return; } nw_connection_set_queue(connection, sSharedResolverQueue); + mtr_weakify(self); nw_connection_set_path_changed_handler(connection, ^(nw_path_t _Nonnull path) { - nw_path_status_t status = nw_path_get_status(path); - if (status == nw_path_status_satisfied) { - MTR_LOG_INFO("%@ path is satisfied", self); - std::lock_guard lock(sConnectivityMonitorLock); - [self _callHandler]; + mtr_strongify(self); + if (self) { + nw_path_status_t status = nw_path_get_status(path); + if (status == nw_path_status_satisfied) { + MTR_LOG_INFO("%@ path is satisfied", self); + std::lock_guard lock(sConnectivityMonitorLock); + [self _callHandler]; + } } }); nw_connection_set_viability_changed_handler(connection, ^(bool viable) { - if (viable) { - std::lock_guard lock(sConnectivityMonitorLock); - MTR_LOG_INFO("%@ connectivity now viable", self); - [self _callHandler]; + mtr_strongify(self); + if (self) { + if (viable) { + std::lock_guard lock(sConnectivityMonitorLock); + MTR_LOG_INFO("%@ connectivity now viable", self); + [self _callHandler]; + } } }); nw_connection_start(connection); From 0d67568a3f2938d1cdcc8850ace47e54416476c7 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Fri, 10 May 2024 11:06:43 +1200 Subject: [PATCH 33/39] Darwin: Address various MTRSetupPayload issues (#33286) * Darwin: Address various MTRSetupPayload issues API: - Conform to NSCopying and implement isEqual / hash - Simplify a number of methods to not return NSError - Add initWithPayload: as a replacement for setupPayloadWithOnboardingPayload:error: - Add initWithQRCode: and initWithManualPairingCode: for cases where payload type is known. - Add vendorElements as a replacement for getAllOptionalVendorData: - Add vendorElementWithTag: - Add removeVendorElementWithTag: - Add addOrReplaceVendorElement: Behaviour fixes: - Allow QRCodes with unknown discovery methods to be parsed - Correctly generate a long manualEntryCode when a non-standard flow is indicated - Include vendor elements in qrCodeString - Preserve vendor elements in encodeWithCoder / initWithCoder Also simplify the implementation by acting as a direct wrapper of chip::SetupPayload. Implement parsing in MTRSetupPayload directly and implement the deprecated MTR*PayloadParser classes in terms of it, instead of the other way around. * Fix lint check for 0x%[^x] to allow "*" * Address review comments * Address review comments around NSNumber * Hide type-specific initializers as per review * Misc tweaks --- .github/workflows/lint.yml | 2 +- .../Framework/CHIP/MTRDefines_Internal.h | 4 + src/darwin/Framework/CHIP/MTRError.mm | 12 + src/darwin/Framework/CHIP/MTRError_Internal.h | 15 +- .../CHIP/MTRManualSetupPayloadParser.h | 2 +- .../CHIP/MTRManualSetupPayloadParser.mm | 40 +- .../CHIP/MTROnboardingPayloadParser.h | 2 +- .../CHIP/MTROnboardingPayloadParser.mm | 41 +- .../CHIP/MTRQRCodeSetupPayloadParser.h | 2 +- .../CHIP/MTRQRCodeSetupPayloadParser.mm | 40 +- src/darwin/Framework/CHIP/MTRSetupPayload.h | 176 +++- src/darwin/Framework/CHIP/MTRSetupPayload.mm | 844 +++++++++++------- .../Framework/CHIP/MTRSetupPayload_Internal.h | 13 +- src/darwin/Framework/CHIP/MTRUtilities.h | 27 + src/darwin/Framework/CHIP/MTRUtilities.mm | 23 + .../CHIPTests/MTRSetupPayloadTests.m | 148 ++- .../Matter.xcodeproj/project.pbxproj | 8 + 17 files changed, 906 insertions(+), 493 deletions(-) create mode 100644 src/darwin/Framework/CHIP/MTRUtilities.h create mode 100644 src/darwin/Framework/CHIP/MTRUtilities.mm diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5f7a956c1ec25e..c810884ed98d30 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -242,7 +242,7 @@ jobs: output. if: always() run: | - git grep -I -n '0x%[0-9l.-]*[^0-9lxX".-]' -- './*' ':(exclude).github/workflows/lint.yml' && exit 1 || exit 0 + git grep -I -n '0x%[0-9l.*-]*[^xX"0-9l.*-]' -- './*' ':(exclude).github/workflows/lint.yml' && exit 1 || exit 0 # git grep exits with 0 if it finds a match, but we want # to fail (exit nonzero) on match. And we want to exclude this file, diff --git a/src/darwin/Framework/CHIP/MTRDefines_Internal.h b/src/darwin/Framework/CHIP/MTRDefines_Internal.h index 6a684f5f879e04..da31ce1b54dda7 100644 --- a/src/darwin/Framework/CHIP/MTRDefines_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDefines_Internal.h @@ -58,5 +58,9 @@ typedef struct {} variable_hidden_by_mtr_hide; // clang-format on +// mtr_[un]likely(expr): Evaluates a boolean expression and hints to the compiler that it is [un]likely to be true. +#define mtr_likely(expr) __builtin_expect(!!(expr), 1) +#define mtr_unlikely(expr) __builtin_expect(!!(expr), 0) + // Default timed interaction timeout, in ms, if another one is not provided. #define MTR_DEFAULT_TIMED_INTERACTION_TIMEOUT_MS 10000 diff --git a/src/darwin/Framework/CHIP/MTRError.mm b/src/darwin/Framework/CHIP/MTRError.mm index d607f00400d158..e268ab49e32cc9 100644 --- a/src/darwin/Framework/CHIP/MTRError.mm +++ b/src/darwin/Framework/CHIP/MTRError.mm @@ -19,6 +19,7 @@ #import "MTRError.h" #import "MTRError_Internal.h" +#import "MTRLogging_Internal.h" #import #import @@ -43,6 +44,11 @@ - (instancetype)initWithError:(CHIP_ERROR)error; @implementation MTRError ++ (NSError *)errorWithCode:(MTRErrorCode)code +{ + return [NSError errorWithDomain:MTRErrorDomain code:code userInfo:nil]; +} + + (NSError *)errorForCHIPErrorCode:(CHIP_ERROR)errorCode { return [MTRError errorForCHIPErrorCode:errorCode logContext:nil]; @@ -337,3 +343,9 @@ - (instancetype)initWithError:(CHIP_ERROR)error } @end + +void MTRThrowInvalidArgument(NSString * reason) +{ + MTR_LOG_ERROR("Invalid argument: %@", reason); + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:reason userInfo:nil]; +} diff --git a/src/darwin/Framework/CHIP/MTRError_Internal.h b/src/darwin/Framework/CHIP/MTRError_Internal.h index 24916082835a6e..c79cc17d95f198 100644 --- a/src/darwin/Framework/CHIP/MTRError_Internal.h +++ b/src/darwin/Framework/CHIP/MTRError_Internal.h @@ -16,16 +16,19 @@ */ #import -#import #import +#import "MTRDefines_Internal.h" + #include #include #include NS_ASSUME_NONNULL_BEGIN +MTR_DIRECT_MEMBERS @interface MTRError : NSObject ++ (NSError *)errorWithCode:(MTRErrorCode)code; + (NSError * _Nullable)errorForCHIPErrorCode:(CHIP_ERROR)errorCode; + (NSError * _Nullable)errorForCHIPErrorCode:(CHIP_ERROR)errorCode logContext:(id _Nullable)contextToLog; + (NSError * _Nullable)errorForIMStatus:(const chip::app::StatusIB &)status; @@ -33,4 +36,14 @@ NS_ASSUME_NONNULL_BEGIN + (CHIP_ERROR)errorToCHIPErrorCode:(NSError * _Nullable)error; @end +// Similar to VerifyOrDie, but throws an NSInvalidArgumentException +#define MTRVerifyArgumentOrDie(cond, reason) \ + do { \ + if (mtr_unlikely(!(cond))) { \ + MTRThrowInvalidArgument(reason); \ + } \ + } while (0) + +MTR_EXTERN _Noreturn void MTRThrowInvalidArgument(NSString * reason); + NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.h b/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.h index 9dc5d702a3c2a4..34a5054cc7bab7 100644 --- a/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.h +++ b/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN -MTR_DEPRECATED("Please use [MTRSetupPayload setupPayloadWithOnboardingPayload:error:]", ios(16.1, 16.4), macos(13.0, 13.3), +MTR_DEPRECATED("Please use -[MTRSetupPayload initWithPayload:]", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)) @interface MTRManualSetupPayloadParser : NSObject - (instancetype)initWithDecimalStringRepresentation:(NSString *)decimalStringRepresentation; diff --git a/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.mm b/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.mm index c1716b513b38a6..a8a4c6bec96c40 100644 --- a/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.mm +++ b/src/darwin/Framework/CHIP/MTRManualSetupPayloadParser.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,56 +14,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #import "MTRManualSetupPayloadParser.h" #import "MTRError_Internal.h" -#import "MTRFramework.h" -#import "MTRLogging_Internal.h" #import "MTRSetupPayload_Internal.h" -#import -#import - -#include - @implementation MTRManualSetupPayloadParser { NSString * _decimalStringRepresentation; - chip::ManualSetupPayloadParser * _chipManualSetupPayloadParser; -} - -+ (void)initialize -{ - MTRFrameworkInit(); } - (id)initWithDecimalStringRepresentation:(NSString *)decimalStringRepresentation { - if (self = [super init]) { - _decimalStringRepresentation = decimalStringRepresentation; - _chipManualSetupPayloadParser = new chip::ManualSetupPayloadParser(std::string([decimalStringRepresentation UTF8String])); - } + self = [super init]; + _decimalStringRepresentation = decimalStringRepresentation; return self; } - (MTRSetupPayload *)populatePayload:(NSError * __autoreleasing *)error { - chip::SetupPayload cPlusPluspayload; - MTRSetupPayload * payload; - - CHIP_ERROR chipError = _chipManualSetupPayloadParser->populatePayload(cPlusPluspayload); - if (chipError == CHIP_NO_ERROR) { - payload = [[MTRSetupPayload alloc] initWithSetupPayload:cPlusPluspayload]; - } else if (error) { - *error = [MTRError errorForCHIPErrorCode:chipError]; + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithManualPairingCode:_decimalStringRepresentation]; + if (!payload && error) { + *error = [MTRError errorWithCode:MTRErrorCodeInvalidArgument]; } - return payload; } -- (void)dealloc -{ - delete _chipManualSetupPayloadParser; - _chipManualSetupPayloadParser = nullptr; -} - @end diff --git a/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.h b/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.h index f607abb89fe616..a875e36db9fb1b 100644 --- a/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.h +++ b/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.h @@ -28,7 +28,7 @@ typedef NS_ENUM(NSUInteger, MTROnboardingPayloadType) { MTROnboardingPayloadTypeNFC } MTR_DEPRECATED("MTROnboardingPayloadType is unused", ios(16.1, 17.0), macos(13.0, 14.0), watchos(9.1, 10.0), tvos(16.1, 17.0)); -MTR_DEPRECATED("Please use [MTRSetupPayload setupPayloadWithOnboardingPayload:error:]", ios(16.1, 17.0), macos(13.0, 14.0), +MTR_DEPRECATED("Please use [MTRSetupPayload initWithPayload:]", ios(16.1, 17.0), macos(13.0, 14.0), watchos(9.1, 10.0), tvos(16.1, 17.0)) @interface MTROnboardingPayloadParser : NSObject diff --git a/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.mm b/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.mm index fb73932d5a3a42..be9a5fc5e1d0fe 100644 --- a/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.mm +++ b/src/darwin/Framework/CHIP/MTROnboardingPayloadParser.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,50 +16,15 @@ */ #import "MTROnboardingPayloadParser.h" -#import "MTRManualSetupPayloadParser.h" -#import "MTRQRCodeSetupPayloadParser.h" + #import "MTRSetupPayload.h" @implementation MTROnboardingPayloadParser -+ (bool)isQRCode:(NSString *)codeString -{ - return [codeString hasPrefix:@"MT:"]; -} - + (MTRSetupPayload * _Nullable)setupPayloadForOnboardingPayload:(NSString *)onboardingPayload error:(NSError * __autoreleasing *)error { - MTRSetupPayload * payload; - // MTROnboardingPayloadTypeNFC is of type QR code and handled same as QR code - MTROnboardingPayloadType type = - [self isQRCode:onboardingPayload] ? MTROnboardingPayloadTypeQRCode : MTROnboardingPayloadTypeManualCode; - switch (type) { - case MTROnboardingPayloadTypeManualCode: - payload = [self setupPayloadForManualCodeOnboardingPayload:onboardingPayload error:error]; - break; - case MTROnboardingPayloadTypeQRCode: - payload = [self setupPayloadForQRCodeOnboardingPayload:onboardingPayload error:error]; - break; - default: - break; - } - return payload; + return [MTRSetupPayload setupPayloadWithOnboardingPayload:onboardingPayload error:error]; } -+ (MTRSetupPayload * _Nullable)setupPayloadForQRCodeOnboardingPayload:(NSString *)onboardingPayload - error:(NSError * __autoreleasing *)error -{ - MTRQRCodeSetupPayloadParser * qrCodeParser = - [[MTRQRCodeSetupPayloadParser alloc] initWithBase38Representation:onboardingPayload]; - return [qrCodeParser populatePayload:error]; -} - -+ (MTRSetupPayload * _Nullable)setupPayloadForManualCodeOnboardingPayload:(NSString *)onboardingPayload - error:(NSError * __autoreleasing *)error -{ - MTRManualSetupPayloadParser * manualParser = - [[MTRManualSetupPayloadParser alloc] initWithDecimalStringRepresentation:onboardingPayload]; - return [manualParser populatePayload:error]; -} @end diff --git a/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.h b/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.h index 5f71b2668c6a6c..771b650cedc7dc 100644 --- a/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.h +++ b/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.h @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN -MTR_DEPRECATED("Please use [MTRSetupPayload setupPayloadWithOnboardingPayload:error:]", ios(16.1, 16.4), macos(13.0, 13.3), +MTR_DEPRECATED("Please use [MTRSetupPayload -initWithPayload:]", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)) @interface MTRQRCodeSetupPayloadParser : NSObject - (instancetype)initWithBase38Representation:(NSString *)base38Representation; diff --git a/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.mm b/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.mm index acfa613bc6626f..2c7701da8fa716 100644 --- a/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.mm +++ b/src/darwin/Framework/CHIP/MTRQRCodeSetupPayloadParser.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,54 +16,28 @@ */ #import "MTRQRCodeSetupPayloadParser.h" + #import "MTRError_Internal.h" -#import "MTRFramework.h" -#import "MTRLogging_Internal.h" #import "MTRSetupPayload_Internal.h" -#import -#import - -#include - @implementation MTRQRCodeSetupPayloadParser { NSString * _base38Representation; - chip::QRCodeSetupPayloadParser * _chipQRCodeSetupPayloadParser; -} - -+ (void)initialize -{ - MTRFrameworkInit(); } - (id)initWithBase38Representation:(NSString *)base38Representation { - if (self = [super init]) { - _base38Representation = base38Representation; - _chipQRCodeSetupPayloadParser = new chip::QRCodeSetupPayloadParser(std::string([base38Representation UTF8String])); - } + self = [super init]; + _base38Representation = base38Representation; return self; } - (MTRSetupPayload *)populatePayload:(NSError * __autoreleasing *)error { - chip::SetupPayload cPlusPluspayload; - MTRSetupPayload * payload; - - CHIP_ERROR chipError = _chipQRCodeSetupPayloadParser->populatePayload(cPlusPluspayload); - if (chipError == CHIP_NO_ERROR) { - payload = [[MTRSetupPayload alloc] initWithSetupPayload:cPlusPluspayload]; - } else if (error) { - *error = [MTRError errorForCHIPErrorCode:chipError]; + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithQRCode:_base38Representation]; + if (!payload && error) { + *error = [MTRError errorWithCode:MTRErrorCodeInvalidArgument]; } - return payload; } -- (void)dealloc -{ - delete _chipQRCodeSetupPayloadParser; - _chipQRCodeSetupPayloadParser = nullptr; -} - @end diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.h b/src/darwin/Framework/CHIP/MTRSetupPayload.h index 7f11fc582ba4b3..5c789f3b794969 100644 --- a/src/darwin/Framework/CHIP/MTRSetupPayload.h +++ b/src/darwin/Framework/CHIP/MTRSetupPayload.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020-2023 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_OPTIONS(NSUInteger, MTRDiscoveryCapabilities) { - MTRDiscoveryCapabilitiesUnknown = 0, // Device capabilities are not known (e.g. all we have is a numeric code). + MTRDiscoveryCapabilitiesUnknown = 0, // Device capabilities are not known (e.g. we parsed a Manual Pairing Code). MTRDiscoveryCapabilitiesNone MTR_DEPRECATED_WITH_REPLACEMENT( "MTRDiscoveryCapabilitiesUnknown", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)) = 0, @@ -28,7 +28,7 @@ typedef NS_OPTIONS(NSUInteger, MTRDiscoveryCapabilities) { MTRDiscoveryCapabilitiesBLE = 1 << 1, // Device supports BLE MTRDiscoveryCapabilitiesOnNetwork = 1 << 2, // Device supports On Network setup - // If new values are added here, update the "description" method to include them. + // Note: New values added here need to be included in MTRDiscoveryCapabilitiesAsString() MTRDiscoveryCapabilitiesAllMask = MTRDiscoveryCapabilitiesSoftAP | MTRDiscoveryCapabilitiesBLE | MTRDiscoveryCapabilitiesOnNetwork, @@ -38,7 +38,7 @@ typedef NS_ENUM(NSUInteger, MTRCommissioningFlow) { MTRCommissioningFlowStandard = 0, // Device automatically enters commissioning mode upon power-up MTRCommissioningFlowUserActionRequired = 1, // Device requires a user interaction to enter commissioning mode MTRCommissioningFlowCustom = 2, // Commissioning steps should be retrieved from the distributed compliance ledger - MTRCommissioningFlowInvalid = 3, + MTRCommissioningFlowInvalid MTR_NEWLY_DEPRECATED("Not a valid MTRCommissioningFlow value") = 3, }; typedef NS_ENUM(NSUInteger, MTROptionalQRCodeInfoType) { @@ -49,36 +49,76 @@ typedef NS_ENUM(NSUInteger, MTROptionalQRCodeInfoType) { }; /** - * An optional information item present in the QR code the setup payload was - * initialized from. + * An optional information item present in the setup payload. + * + * Note that while the Matter specification allows elements containing + * arbitrary TLV data types, this implementation currently only supports + * String and Int32 values. + * + * Objects of this type are immutable; calling any deprecated property + * setters has no effect. */ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) -@interface MTROptionalQRCodeInfo : NSObject +@interface MTROptionalQRCodeInfo : NSObject /* (see below) */ -@property (nonatomic, assign) MTROptionalQRCodeInfoType type MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +/** + * Initializes the object with a tag and string value. + * The tag must be in the range 0x80 - 0xFF. + */ +- (instancetype)initWithTag:(NSNumber *)tag stringValue:(NSString *)value MTR_NEWLY_AVAILABLE; /** - * The numeric value of the TLV tag for this information item. + * Initializes the object with a tag and int32 value. + * The tag must be in the range 0x80 - 0xFF. */ -@property (nonatomic, copy) NSNumber * tag; +- (instancetype)initWithTag:(NSNumber *)tag int32Value:(int32_t)value MTR_NEWLY_AVAILABLE; + +@property (nonatomic, readonly, assign) MTROptionalQRCodeInfoType type MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); /** - * Exactly one of integerValue and stringValue will be non-nil, depending on the - * the value of "type". + * The vendor-specific TLV tag number for this information item. + * + * Vendor-specific elements have tags in the range 0x80 - 0xFF. */ -@property (nonatomic, copy, nullable) NSNumber * integerValue; -@property (nonatomic, copy, nullable) NSString * stringValue; +@property (nonatomic, readonly, copy) NSNumber * tag; + +/** + * The value held in this extension element, + * if `type` is an integer type, or nil otherwise. + */ +@property (nonatomic, readonly, copy, nullable) NSNumber * integerValue; + +/** + * The value held in this extension element, + * if `type` is `MTROptionalQRCodeInfoTypeString`, or nil otherwise. + */ +@property (nonatomic, readonly, copy, nullable) NSString * stringValue; @end +MTR_NEWLY_AVAILABLE +@interface MTROptionalQRCodeInfo () +@end + /** - * A setup payload that can be created from a numeric code or QR code and - * serialized to a numeric code or QR code, though serializing to QR code after - * creating from numeric code will not work, because some required information - * will be missing. + * A Matter Onboarding Payload. + * + * It can be represented as a numeric Manual Pairing Code or as QR Code. + * The QR Code format contains more information though, so creating a + * QR Code from a payload that was initialized from a Manual Pairing Code + * will not work, because some required information will be missing. + * + * This class can also be used to create an onboarding payload directly + * from the underlying values (passcode, discriminator, etc). */ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) -@interface MTRSetupPayload : NSObject +@interface MTRSetupPayload : NSObject /* also (see below) */ + +/** + * Initializes the payload object from the provide QR Code or Manual Pairing Code string. + * Returns nil if the payload is not valid. + */ +- (nullable instancetype)initWithPayload:(NSString *)payload MTR_NEWLY_AVAILABLE; @property (nonatomic, copy) NSNumber * version; @property (nonatomic, copy) NSNumber * vendorID; @@ -92,19 +132,45 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) */ @property (nonatomic, assign) MTRDiscoveryCapabilities discoveryCapabilities MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); + @property (nonatomic, copy) NSNumber * discriminator; /** * If hasShortDiscriminator is true, the discriminator value contains just the * high 4 bits of the full discriminator. For example, if * hasShortDiscriminator is true and discriminator is 0xA, then the full - * discriminator can be anything in the range 0xA00 t0 0xAFF. + * discriminator can be anything in the range 0xA00 to 0xAFF. */ @property (nonatomic, assign) BOOL hasShortDiscriminator; + @property (nonatomic, copy) NSNumber * setupPasscode MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4)); +/** + * The value of the Serial Number extension element, if any. + */ @property (nonatomic, copy, nullable) NSString * serialNumber; -- (NSArray * _Nullable)getAllOptionalVendorData:(NSError * __autoreleasing *)error; + +/** + * The list of Manufacturer-specific extension elements contained in the setup code. May be empty. + */ +@property (nonatomic, readonly, copy) NSArray * vendorElements MTR_NEWLY_AVAILABLE; + +/** + * Returns the Manufacturer-specific extension element with the specified tag, if any. + * The tag must be in the range 0x80 - 0xFF. + */ +- (nullable MTROptionalQRCodeInfo *)vendorElementWithTag:(NSNumber *)tag MTR_NEWLY_AVAILABLE; + +/** + * Removes the extension element with the specified tag, if any. + * The tag must be in the range 0x80 - 0xFF. + */ +- (void)removeVendorElementWithTag:(NSNumber *)tag MTR_NEWLY_AVAILABLE; + +/** + * Adds or replaces a Manufacturer-specific extension element. + */ +- (void)addOrReplaceVendorElement:(MTROptionalQRCodeInfo *)element MTR_NEWLY_AVAILABLE; /** * Generate a random Matter-valid setup PIN. @@ -116,15 +182,6 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) */ + (NSNumber *)generateRandomSetupPasscode MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)); -/** - * Create an MTRSetupPayload with the given onboarding payload. - * - * Will return nil on errors (e.g. if the onboarding payload cannot be parsed). - */ -+ (MTRSetupPayload * _Nullable)setupPayloadWithOnboardingPayload:(NSString *)onboardingPayload - error:(NSError * __autoreleasing *)error - MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)); - /** * Initialize an MTRSetupPayload with the given passcode and discriminator. * This will pre-set version, product id, and vendor id to 0. @@ -132,39 +189,76 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (instancetype)initWithSetupPasscode:(NSNumber *)setupPasscode discriminator:(NSNumber *)discriminator MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)); -/** Get 11 digit manual entry code from the setup payload. */ -- (NSString * _Nullable)manualEntryCode; +/** + * Creates a Manual Pairing Code from this setup payload. + * Returns nil if this payload cannot be represented as a valid Manual Pairing Code. + * + * The following properties must be populated for a valid Manual Pairing Code: + * - setupPasscode + * - discriminator (short or long) + * + * In most cases the pairing code will be 11 digits long. If the payload indicates + * a `commissioningFlow` other than `MTRCommissioningFlowStandard`, a 21 digit code + * will be produced that includes the vendorID and productID values. + */ +- (nullable NSString *)manualEntryCode; /** - * Get a QR code from the setup payload. + * Creates a QR Code payload from this setup payload. + * Returns nil if this payload cannot be represented as a valid QR Code. * - * Returns nil on failure (e.g. if the setup payload does not have all the - * information a QR code needs). + * The following properties must be populated for a valid QR Code: + * - setupPasscode + * - discriminator (must be long) + * - discoveryCapabilities (not MTRDiscoveryCapabilitiesUnknown) */ -- (NSString * _Nullable)qrCodeString:(NSError * __autoreleasing *)error - MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)); +- (NSString * _Nullable)qrCodeString MTR_NEWLY_AVAILABLE; @end +MTR_NEWLY_AVAILABLE +@interface MTRSetupPayload () +@end + @interface MTROptionalQRCodeInfo (Deprecated) -@property (nonatomic, copy) - NSNumber * infoType MTR_DEPRECATED("Please use type", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); +- (instancetype)init MTR_NEWLY_DEPRECATED("Please use -initWithTag:...value:"); + +@property (nonatomic, copy) NSNumber * infoType + MTR_DEPRECATED("Please use type", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); +- (void)setType:(MTROptionalQRCodeInfoType)type MTR_NEWLY_DEPRECATED("MTROptionalQRCodeInfo is immutable"); +- (void)setTag:(NSNumber *)tag MTR_NEWLY_DEPRECATED("MTROptionalQRCodeInfo is immutable"); +- (void)setIntegerValue:(NSNumber *)integerValue MTR_NEWLY_DEPRECATED("MTROptionalQRCodeInfo is immutable"); +- (void)setStringValue:(NSString *)stringValue MTR_NEWLY_DEPRECATED("MTROptionalQRCodeInfo is immutable"); @end @interface MTRSetupPayload (Deprecated) @property (nonatomic, copy, nullable) NSNumber * rendezvousInformation MTR_DEPRECATED( "Please use discoveryCapabilities", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); + @property (nonatomic, copy) NSNumber * setUpPINCode MTR_DEPRECATED( "Please use setupPasscode", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); -- (instancetype)init MTR_DEPRECATED("Please use initWithSetupPasscode or setupPayloadWithOnboardingPayload", ios(16.1, 16.4), +- (instancetype)init MTR_DEPRECATED("Please use -initWithSetupPasscode:discriminator: or -initWithPayload:", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); -+ (instancetype)new MTR_DEPRECATED("Please use initWithSetupPasscode or setupPayloadWithOnboardingPayload", ios(16.1, 16.4), + ++ (instancetype)new MTR_DEPRECATED("Please use -initWithSetupPasscode:discriminator: or -initWithPayload:", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4)); ++ (MTRSetupPayload * _Nullable)setupPayloadWithOnboardingPayload:(NSString *)onboardingPayload + error:(NSError * __autoreleasing *)error + MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)) + MTR_NEWLY_DEPRECATED("Please use -initWithPayload:"); + +- (NSString * _Nullable)qrCodeString:(NSError * __autoreleasing *)error + MTR_AVAILABLE(ios(16.2), macos(13.1), watchos(9.2), tvos(16.2)) + MTR_NEWLY_DEPRECATED("Please use -qrCodeString"); + +- (NSArray * _Nullable)getAllOptionalVendorData:(NSError * __autoreleasing *)error + MTR_NEWLY_DEPRECATED("Please use -vendorElements"); + @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload.mm b/src/darwin/Framework/CHIP/MTRSetupPayload.mm index d5788c63dc6f6c..98d9f2b342c909 100644 --- a/src/darwin/Framework/CHIP/MTRSetupPayload.mm +++ b/src/darwin/Framework/CHIP/MTRSetupPayload.mm @@ -19,251 +19,520 @@ #import "MTRError_Internal.h" #import "MTRFramework.h" -#import "MTROnboardingPayloadParser.h" +#import "MTRLogging_Internal.h" +#import "MTRUtilities.h" +#include #include +#include #include +#include #include #include -@implementation MTROptionalQRCodeInfo -@end - MTR_DIRECT_MEMBERS -@implementation MTRSetupPayload { - chip::SetupPayload _chipSetupPayload; +@implementation MTROptionalQRCodeInfo { + chip::OptionalQRCodeInfo _info; } -+ (void)initialize +static uint8_t ValidateVendorTag(NSNumber * tag) { - // Need to make sure we set up Platform memory stuff before we start - // serializing payloads. - MTRFrameworkInit(); + auto integerValue = tag.integerValue; + auto tagValue = static_cast(integerValue); + MTRVerifyArgumentOrDie(tag != nil && chip::CanCastTo(integerValue) && chip::SetupPayload::IsVendorTag(tagValue), @"tag must be a vendor tag (0x80 - 0xFF)"); + return tagValue; } -- (MTRDiscoveryCapabilities)convertRendezvousFlags:(const chip::Optional &)value +- (instancetype)initWithTag:(NSNumber *)tag int32Value:(int32_t)value { - if (!value.HasValue()) { - return MTRDiscoveryCapabilitiesUnknown; - } + self = [super init]; + _info.type = chip::optionalQRCodeInfoTypeInt32; + _info.tag = ValidateVendorTag(tag); + _info.int32 = value; + return self; +} - NSUInteger flags = 0; - if (value.Value().Has(chip::RendezvousInformationFlag::kBLE)) { - flags |= MTRDiscoveryCapabilitiesBLE; - } - if (value.Value().Has(chip::RendezvousInformationFlag::kSoftAP)) { - flags |= MTRDiscoveryCapabilitiesSoftAP; - } - if (value.Value().Has(chip::RendezvousInformationFlag::kOnNetwork)) { - flags |= MTRDiscoveryCapabilitiesOnNetwork; - } - if (flags == MTRDiscoveryCapabilitiesUnknown) { - // OnNetwork has to be supported! - flags = MTRDiscoveryCapabilitiesOnNetwork; - } - return flags; +- (instancetype)initWithTag:(NSNumber *)tag stringValue:(NSString *)value +{ + self = [super init]; + _info.type = chip::optionalQRCodeInfoTypeString; + _info.tag = ValidateVendorTag(tag); + MTRVerifyArgumentOrDie(value != nil, @"value"); + _info.data = value.UTF8String; + return self; +} + +- (nullable instancetype)initWithQRCodeInfo:(chip::OptionalQRCodeInfo const &)info +{ + self = [super init]; + _info = info; + // Don't expose objects with an out-of-range tag or invalid type + VerifyOrReturnValue(chip::SetupPayload::IsVendorTag(_info.tag), nil); + VerifyOrReturnValue(self.type != MTROptionalQRCodeInfoTypeUnknown, nil); + return self; } -+ (chip::Optional)convertDiscoveryCapabilities:(MTRDiscoveryCapabilities)value +- (CHIP_ERROR)addAsVendorElementTo:(chip::SetupPayload &)payload { - if (value == MTRDiscoveryCapabilitiesUnknown) { - return chip::NullOptional; + switch (_info.type) { + case chip::optionalQRCodeInfoTypeString: + return payload.addOptionalVendorData(_info.tag, _info.data); + case chip::optionalQRCodeInfoTypeInt32: + return payload.addOptionalVendorData(_info.tag, _info.int32); + default: + return CHIP_ERROR_INCORRECT_STATE; } +} - chip::RendezvousInformationFlags flags; - if (value & MTRDiscoveryCapabilitiesBLE) { - flags.Set(chip::RendezvousInformationFlag::kBLE); +- (MTROptionalQRCodeInfoType)type +{ + // The way OptionalQRCodeInfo uses what are effectively C type identifiers (uint32 etc) + // rather than TLV types is not ideal. If we add support for additional integer types + // we should consider replacing MTROptionalQRCodeInfoTypeInt32 with + // MTROptionalQRCodeInfoTypeInteger and hiding the low-level C representation. + switch (_info.type) { + case chip::optionalQRCodeInfoTypeString: + return MTROptionalQRCodeInfoTypeString; + case chip::optionalQRCodeInfoTypeInt32: + return MTROptionalQRCodeInfoTypeInt32; + // No 'default:' so we get a warning if new types are added. + // Note: isEqual: also switches over these types. + // OptionalQRCodeInfo does not support these types + case chip::optionalQRCodeInfoTypeInt64: + case chip::optionalQRCodeInfoTypeUInt32: + case chip::optionalQRCodeInfoTypeUInt64: + // We should never see the unknown type + case chip::optionalQRCodeInfoTypeUnknown: + /* fall through */; + } + return MTROptionalQRCodeInfoTypeUnknown; +} + +- (NSNumber *)tag +{ + return @(_info.tag); +} + +- (NSNumber *)integerValue +{ + VerifyOrReturnValue(_info.type == chip::optionalQRCodeInfoTypeInt32, nil); + return @(_info.int32); +} + +- (NSString *)stringValue +{ + VerifyOrReturnValue(_info.type == chip::optionalQRCodeInfoTypeString, nil); + return [NSString stringWithUTF8String:_info.data.c_str()]; +} + +- (id)copyWithZone:(NSZone *)zone +{ + return self; // immutable +} + +- (NSUInteger)hash +{ + return _info.type << 8 | _info.tag; +} + +- (BOOL)isEqual:(id)object +{ + VerifyOrReturnValue([object class] == [self class], NO); + MTROptionalQRCodeInfo * other = object; + VerifyOrReturnValue(_info.tag == other->_info.tag, NO); + VerifyOrReturnValue(_info.type == other->_info.type, NO); + switch (_info.type) { + case chip::optionalQRCodeInfoTypeString: + return _info.data == other->_info.data; + case chip::optionalQRCodeInfoTypeInt32: + return _info.int32 == other->_info.int32; + default: + return NO; // unreachable, type is checked in init } +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"0x%02x=%@", self.tag.unsignedCharValue, self.integerValue ?: self.stringValue]; +} + +@end + +static constexpr uint8_t kShortDiscriminatorMask = (1 << chip::SetupDiscriminator::kShortBits) - 1; +static constexpr uint16_t kLongDiscriminatorMask = (1 << chip::SetupDiscriminator::kLongBits) - 1; + +static MTRDiscoveryCapabilities KnownDiscoveryCapabilities(NSUInteger value) +{ + // A known but 0 value cannot be represented by MTRDiscoveryCapabilities + // since MTRDiscoveryCapabilitiesUnknown represents an absent value. + // However such a 0 value is not logically valid, because OnNetwork must + // always be supported. So just return that if we get a value of 0. + return (value != MTRDiscoveryCapabilitiesUnknown ? value : MTRDiscoveryCapabilitiesOnNetwork); +} + +static NSString * MTRDiscoveryCapabilitiesAsString(MTRDiscoveryCapabilities value) +{ + VerifyOrReturnValue(value != MTRDiscoveryCapabilitiesUnknown, @"Unknown"); + NSMutableString * capabilities = [NSMutableString string]; if (value & MTRDiscoveryCapabilitiesSoftAP) { - flags.Set(chip::RendezvousInformationFlag::kSoftAP); + [capabilities appendString:@"|SoftAP"]; + value &= ~MTRDiscoveryCapabilitiesSoftAP; + } + if (value & MTRDiscoveryCapabilitiesBLE) { + [capabilities appendString:@"|BLE"]; + value &= ~MTRDiscoveryCapabilitiesBLE; } if (value & MTRDiscoveryCapabilitiesOnNetwork) { - flags.Set(chip::RendezvousInformationFlag::kOnNetwork); + [capabilities appendString:@"|OnNetwork"]; + value &= ~MTRDiscoveryCapabilitiesOnNetwork; + } + if (value != 0) { + [capabilities appendFormat:@"|0x%llx", (unsigned long long) value]; } - return chip::MakeOptional(flags); + return [capabilities substringFromIndex:1]; } -- (MTRCommissioningFlow)convertCommissioningFlow:(chip::CommissioningFlow)value +MTR_DIRECT_MEMBERS +@implementation MTRSetupPayload { + // Apart from the additional logic to handle discriminators detailed below, + // this class is simply a wrapper around this underlying SetupPayload. + chip::SetupPayload _payload; + + // SetupPayload deals with the discriminator value and its shortness as a composite + // SetupDiscriminator value, which is arguably a tidier API than letting clients + // set a value first and only later tell us whether it's long or short. But that is + // what our API does, so we need to continue to support it. To make this work, we + // keep track of the potentially-long value that was set by the client. + NSNumber * _Nullable _shadowDiscriminator; +} + ++ (void)initialize { - if (value == chip::CommissioningFlow::kStandard) { - return MTRCommissioningFlowStandard; - } - if (value == chip::CommissioningFlow::kUserActionRequired) { - return MTRCommissioningFlowUserActionRequired; - } - if (value == chip::CommissioningFlow::kCustom) { - return MTRCommissioningFlowCustom; - } - return MTRCommissioningFlowInvalid; + // Some aspects of working with chip::SetupPayload use Platform memory primitives. + MTRFrameworkInit(); } -+ (chip::CommissioningFlow)unconvertCommissioningFlow:(MTRCommissioningFlow)value +- (nullable instancetype)initWithPayload:(NSString *)payload { - if (value == MTRCommissioningFlowStandard) { - return chip::CommissioningFlow::kStandard; - } - if (value == MTRCommissioningFlowUserActionRequired) { - return chip::CommissioningFlow::kUserActionRequired; + return ([payload hasPrefix:@"MT:"]) ? [self initWithQRCode:payload] : [self initWithManualPairingCode:payload]; +} + +- (CHIP_ERROR)initializeFromQRCode:(NSString *)qrCode +{ + std::string string([(qrCode ?: @"") UTF8String]); // handle nil gracefully + chip::QRCodeSetupPayloadParser parser(string); + return parser.populatePayload(_payload); +} + +- (nullable instancetype)initWithQRCode:(NSString *)qrCodePayload +{ + self = [super init]; + CHIP_ERROR err = [self initializeFromQRCode:qrCodePayload]; + if (err != CHIP_NO_ERROR) { + MTR_LOG_ERROR("Failed to parse QR Code payload: %" CHIP_ERROR_FORMAT, err.Format()); + return nil; } - if (value == MTRCommissioningFlowCustom) { - return chip::CommissioningFlow::kCustom; + if (!_payload.isValidQRCodePayload(chip::PayloadContents::ValidationMode::kConsume)) { + MTR_LOG_ERROR("Invalid QR Code payload"); + return nil; } - // It's MTRCommissioningFlowInvalid ... now what? But in practice - // this is not called when we have MTRCommissioningFlowInvalid. - return chip::CommissioningFlow::kStandard; + + return self; } -- (instancetype)initWithSetupPayload:(chip::SetupPayload)setupPayload +- (nullable instancetype)initWithManualPairingCode:(NSString *)manualCode { - if (self = [super init]) { - _chipSetupPayload = setupPayload; - _version = [NSNumber numberWithUnsignedChar:setupPayload.version]; - _vendorID = [NSNumber numberWithUnsignedShort:setupPayload.vendorID]; - _productID = [NSNumber numberWithUnsignedShort:setupPayload.productID]; - _commissioningFlow = [self convertCommissioningFlow:setupPayload.commissioningFlow]; - _discoveryCapabilities = [self convertRendezvousFlags:setupPayload.rendezvousInformation]; - _hasShortDiscriminator = setupPayload.discriminator.IsShortDiscriminator(); - if (_hasShortDiscriminator) { - _discriminator = [NSNumber numberWithUnsignedShort:setupPayload.discriminator.GetShortValue()]; - } else { - _discriminator = [NSNumber numberWithUnsignedShort:setupPayload.discriminator.GetLongValue()]; - } - _setupPasscode = [NSNumber numberWithUnsignedInt:setupPayload.setUpPINCode]; + self = [super init]; - [self getSerialNumber:setupPayload]; + std::string string([(manualCode ?: @"") UTF8String]); // handle nil gracefully + chip::ManualSetupPayloadParser parser(string); + CHIP_ERROR err = parser.populatePayload(_payload); + if (err != CHIP_NO_ERROR) { + MTR_LOG_ERROR("Failed to parse Manual Pairing Code: %" CHIP_ERROR_FORMAT, err.Format()); + return nil; } + if (!_payload.isValidManualCode(chip::PayloadContents::ValidationMode::kConsume)) { + MTR_LOG_ERROR("Invalid Manual Pairing Code"); + return nil; + } + return self; } - (instancetype)initWithSetupPasscode:(NSNumber *)setupPasscode discriminator:(NSNumber *)discriminator { - if (self = [super init]) { - _version = @(0); // Only supported Matter version so far. - _vendorID = @(0); // Not available. - _productID = @(0); // Not available. - _commissioningFlow = MTRCommissioningFlowStandard; - // We are using a long discriminator, so have to have a known - // discoveryCapabilities to be a valid payload. Just default to "try - // all discovery methods". - _discoveryCapabilities = MTRDiscoveryCapabilitiesAllMask; - _hasShortDiscriminator = NO; - _discriminator = discriminator; - _setupPasscode = setupPasscode; - _serialNumber = nil; - } + self = [super init]; + + // A default-constructed SetupPayload already has most of the expected + // default values. Set discoveryCapabilities to "all known methods" so + // we're representing a valid QR Code payload. + self.setupPasscode = setupPasscode; + self.discriminator = discriminator; + self.discoveryCapabilities = MTRDiscoveryCapabilitiesAllMask; + return self; } -- (void)getSerialNumber:(chip::SetupPayload)setupPayload +- (instancetype)initWithSetupPayload:(chip::SetupPayload)setupPayload +{ + self = [super init]; + _payload = setupPayload; + return self; +} + +#pragma mark - Mutable properties + +- (NSNumber *)version +{ + return @(_payload.version); +} + +- (void)setVersion:(NSNumber *)version +{ + _payload.version = static_cast(version.unsignedIntegerValue); +} + +- (NSNumber *)vendorID +{ + return @(_payload.vendorID); +} + +- (void)setVendorID:(NSNumber *)vendorID +{ + _payload.vendorID = static_cast(vendorID.unsignedIntegerValue); +} + +- (NSNumber *)productID { - std::string serialNumberC; - CHIP_ERROR err = setupPayload.getSerialNumber(serialNumberC); - if (err == CHIP_NO_ERROR) { - _serialNumber = [NSString stringWithUTF8String:serialNumberC.c_str()]; + return @(_payload.productID); +} + +- (void)setProductID:(NSNumber *)productID +{ + _payload.productID = static_cast(productID.unsignedIntegerValue); +} + +- (MTRCommissioningFlow)commissioningFlow +{ + // To avoid ending up with special logic to handle MTRCommissioningFlowInvalid, + // we simply cast between MTRCommissioningFlow and chip::CommissioningFlow. + // Both types represent the same set of values defined in the Matter spec. + using chip::CommissioningFlow; + static_assert(static_cast(MTRCommissioningFlowStandard) == CommissioningFlow::kStandard); + static_assert(static_cast(MTRCommissioningFlowUserActionRequired) == CommissioningFlow::kUserActionRequired); + static_assert(static_cast(MTRCommissioningFlowCustom) == CommissioningFlow::kCustom); + return static_cast(_payload.commissioningFlow); +} + +- (void)setCommissioningFlow:(MTRCommissioningFlow)commissioningFlow +{ + _payload.commissioningFlow = static_cast(commissioningFlow); +} + +- (MTRDiscoveryCapabilities)discoveryCapabilities +{ + VerifyOrReturnValue(_payload.rendezvousInformation.HasValue(), MTRDiscoveryCapabilitiesUnknown); + + // MTRDiscoveryCapabilities and chip::RendezvousInformationFlag represent + // the same set of bit flags from the Matter spec, so we can simply cast. + using RendezvousFlag = chip::RendezvousInformationFlag; + static_assert(static_cast(MTRDiscoveryCapabilitiesSoftAP) == RendezvousFlag::kSoftAP); + static_assert(static_cast(MTRDiscoveryCapabilitiesBLE) == RendezvousFlag::kBLE); + static_assert(static_cast(MTRDiscoveryCapabilitiesOnNetwork) == RendezvousFlag::kOnNetwork); + auto value = static_cast(_payload.rendezvousInformation.Value().Raw()); + + // Ensure a known (HasValue()) but 0 value does not map to MTRDiscoveryCapabilitiesUnknown. + return KnownDiscoveryCapabilities(value); +} + +- (void)setDiscoveryCapabilities:(MTRDiscoveryCapabilities)discoveryCapabilities +{ + if (discoveryCapabilities == MTRDiscoveryCapabilitiesUnknown) { + _payload.rendezvousInformation.ClearValue(); + } else { + auto flags = static_cast(discoveryCapabilities); + _payload.rendezvousInformation.SetValue(chip::RendezvousInformationFlags(flags)); } } -- (NSArray *)getAllOptionalVendorData:(NSError * __autoreleasing *)error +- (NSNumber *)discriminator { - NSMutableArray * allOptionalData = [NSMutableArray new]; - std::vector chipOptionalData = _chipSetupPayload.getAllOptionalVendorData(); - for (chip::OptionalQRCodeInfo chipInfo : chipOptionalData) { - MTROptionalQRCodeInfo * info = [MTROptionalQRCodeInfo new]; - info.tag = [NSNumber numberWithUnsignedChar:chipInfo.tag]; - switch (chipInfo.type) { - case chip::optionalQRCodeInfoTypeString: - info.type = MTROptionalQRCodeInfoTypeString; - info.stringValue = [NSString stringWithUTF8String:chipInfo.data.c_str()]; - break; - case chip::optionalQRCodeInfoTypeInt32: - info.type = MTROptionalQRCodeInfoTypeInt32; - info.integerValue = [NSNumber numberWithInt:chipInfo.int32]; - break; - default: - if (error) { - *error = [NSError errorWithDomain:MTRErrorDomain code:MTRErrorCodeInvalidArgument userInfo:nil]; - } - return nil; - } - [allOptionalData addObject:info]; + VerifyOrReturnValue(_shadowDiscriminator == nil, _shadowDiscriminator); + auto & pd = _payload.discriminator; + return @(pd.IsShortDiscriminator() ? pd.GetShortValue() : pd.GetLongValue()); +} + +- (void)setDiscriminator:(uint16_t)discriminator isShort:(BOOL)isShort +{ + if (isShort) { + _payload.discriminator.SetShortValue(discriminator & kShortDiscriminatorMask); + _shadowDiscriminator = @(discriminator); // keep as a shadow value + } else { + _payload.discriminator.SetLongValue(discriminator); + _shadowDiscriminator = nil; // no need to keep a shadow copy } - return allOptionalData; } -+ (NSUInteger)generateRandomPIN +- (void)setDiscriminator:(NSNumber *)discriminator { - return [[MTRSetupPayload generateRandomSetupPasscode] unsignedIntValue]; + // Truncate down to the range of a long discriminator. Then update + // our SetupPayload with the value, but keep the current shortness. + uint16_t value = discriminator.unsignedIntegerValue & kLongDiscriminatorMask; + [self setDiscriminator:value isShort:self.hasShortDiscriminator]; } -+ (NSNumber *)generateRandomSetupPasscode +- (BOOL)hasShortDiscriminator { - do { - // Make sure the thing we generate is in the right range. - uint32_t setupPIN = arc4random_uniform(chip::kSetupPINCodeMaximumValue) + 1; - if (chip::SetupPayload::IsValidSetupPIN(setupPIN)) { - return @(setupPIN); - } + return _payload.discriminator.IsShortDiscriminator(); +} - // We got pretty unlikely with our random number generation. Just try - // again. The chance that this loop does not terminate in a reasonable - // amount of time is astronomically low, assuming arc4random_uniform is not - // broken. - } while (true); +- (void)setHasShortDiscriminator:(BOOL)hasShortDiscriminator +{ + VerifyOrReturn(hasShortDiscriminator != self.hasShortDiscriminator); + [self setDiscriminator:self.discriminator.unsignedShortValue isShort:hasShortDiscriminator]; +} - // Not reached. - return @(chip::kSetupPINCodeUndefinedValue); +- (NSNumber *)setupPasscode +{ + return @(_payload.setUpPINCode); } -+ (bool)isQRCode:(NSString *)onboardingPayload +- (void)setSetupPasscode:(NSNumber *)setupPasscode { - return [onboardingPayload hasPrefix:@"MT:"]; + _payload.setUpPINCode = static_cast(setupPasscode.unsignedIntegerValue); } -+ (MTRSetupPayload * _Nullable)setupPayloadWithOnboardingPayload:(NSString *)onboardingPayload - error:(NSError * __autoreleasing *)error +- (nullable NSString *)serialNumber { - // TODO: Do we actually need the MTROnboardingPayloadParser abstraction? - MTRSetupPayload * payload = [MTROnboardingPayloadParser setupPayloadForOnboardingPayload:onboardingPayload error:error]; - if (payload == nil) { - return nil; - } + std::string value; + VerifyOrReturnValue(_payload.getSerialNumber(value) == CHIP_NO_ERROR, nil); + return [NSString stringWithUTF8String:value.c_str()]; +} - bool isQRCode = [MTRSetupPayload isQRCode:onboardingPayload]; - bool validPayload; - if (isQRCode) { - validPayload = payload->_chipSetupPayload.isValidQRCodePayload(); +- (void)setSerialNumber:(nullable NSString *)serialNumber +{ + if (serialNumber) { + NSString * existing = self.serialNumber; + if (existing) { + // The underlying TLV tag can be encoded as either a string or an integer, + // avoid changing it if the represented serial number is not changing. + VerifyOrReturn(![existing isEqualToString:serialNumber]); + _payload.removeSerialNumber(); + } + CHIP_ERROR err = _payload.addSerialNumber(serialNumber.UTF8String); + if (err != CHIP_NO_ERROR) { + MTR_LOG_ERROR("Ignoring unexpected error in SetupPayload::addSerialNumber: %" CHIP_ERROR_FORMAT, err.Format()); + } } else { - validPayload = payload->_chipSetupPayload.isValidManualCode(); + _payload.removeSerialNumber(); } +} - if (!validPayload) { - if (error) { - *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT logContext:onboardingPayload]; +- (NSArray *)vendorElements +{ + std::vector elements = _payload.getAllOptionalVendorData(); + VerifyOrReturnValue(!elements.empty(), @[]); + NSMutableArray * infos = [[NSMutableArray alloc] initWithCapacity:elements.size()]; + for (auto const & element : elements) { + MTROptionalQRCodeInfo * info = [[MTROptionalQRCodeInfo alloc] initWithQRCodeInfo:element]; + if (info != nil) { // ignore invalid elements (there shouldn't be any) + [infos addObject:info]; } - return nil; } + return infos; +} - return payload; +- (MTROptionalQRCodeInfo *)vendorElementWithTag:(NSNumber *)tag +{ + chip::OptionalQRCodeInfo element; + VerifyOrReturnValue(_payload.getOptionalVendorData(ValidateVendorTag(tag), element) == CHIP_NO_ERROR, nil); + return [[MTROptionalQRCodeInfo alloc] initWithQRCodeInfo:element]; } -- (NSString *)description +- (void)removeVendorElementWithTag:(NSNumber *)tag { - NSMutableArray * capabilities = [NSMutableArray array]; - if (self.discoveryCapabilities & MTRDiscoveryCapabilitiesSoftAP) { - [capabilities addObject:@"SoftAP"]; - } - if (self.discoveryCapabilities & MTRDiscoveryCapabilitiesBLE) { - [capabilities addObject:@"BLE"]; + _payload.removeOptionalVendorData(ValidateVendorTag(tag)); +} + +- (void)addOrReplaceVendorElement:(MTROptionalQRCodeInfo *)element +{ + MTRVerifyArgumentOrDie(element != nil, @"element"); + CHIP_ERROR err = [element addAsVendorElementTo:_payload]; + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, NotSpecified, "Internal error: %" CHIP_ERROR_FORMAT, err.Format()); +} + +#pragma mark - Export methods + +- (nullable NSString *)manualEntryCode +{ + chip::ManualSetupPayloadGenerator generator(_payload); + std::string result; + VerifyOrReturnValue(generator.payloadDecimalStringRepresentation(result) == CHIP_NO_ERROR, nil); + return [NSString stringWithUTF8String:result.c_str()]; +} + +- (nullable NSString *)qrCodeString +{ + return [self qrCodeStringSkippingValidation:NO]; +} + +- (nullable NSString *)qrCodeStringSkippingValidation:(BOOL)allowInvalid +{ + chip::QRCodeSetupPayloadGenerator generator(_payload); + generator.SetAllowInvalidPayload(allowInvalid); + std::string result; + CHIP_ERROR err = generator.payloadBase38RepresentationWithAutoTLVBuffer(result); + if (allowInvalid) { + // Encoding should always work if invalid payloads are allowed + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, NotSpecified, "Internal error: %" CHIP_ERROR_FORMAT, err.Format()); + } else { + VerifyOrReturnValue(err == CHIP_NO_ERROR, nil); } - if (self.discoveryCapabilities & MTRDiscoveryCapabilitiesOnNetwork) { - [capabilities addObject:@"OnNetwork"]; + return [NSString stringWithUTF8String:result.c_str()]; +} + +#pragma mark - Miscellaneous + +- (id)copyWithZone:(NSZone *)zone +{ + MTRSetupPayload * copy = [[MTRSetupPayload alloc] initWithSetupPayload:_payload]; + copy->_shadowDiscriminator = _shadowDiscriminator; + return copy; +} + +- (NSUInteger)hash +{ + return self.discriminator.unsignedIntegerValue; +} + +- (BOOL)isEqual:(id)object +{ + VerifyOrReturnValue([object class] == [self class], NO); + MTRSetupPayload * other = object; + VerifyOrReturnValue(_payload == other->_payload, NO); + VerifyOrReturnValue(MTREqualObjects(_shadowDiscriminator, other->_shadowDiscriminator), NO); + return YES; +} + +- (NSString *)description +{ + // Note: The description does not include the passcode for security reasons! + + NSMutableString * result = [NSMutableString stringWithFormat:@"", - self.discriminator.unsignedIntValue, self.hasShortDiscriminator ? @"YES" : @"NO", [capabilities componentsJoinedByString:@"|"]]; + [result appendString:@">"]; + return result; } #pragma mark - NSSecureCoding @@ -272,11 +541,12 @@ - (NSString *)description static NSString * const MTRSetupPayloadCodingKeyVendorID = @"MTRSP.ck.vendorID"; static NSString * const MTRSetupPayloadCodingKeyProductID = @"MTRSP.ck.productID"; static NSString * const MTRSetupPayloadCodingKeyCommissioningFlow = @"MTRSP.ck.commissioningFlow"; -static NSString * const MTRSetupPayloadCodingKeyDiscoveryCapabilities = @"MTRSP.ck.rendezvousFlags"; +static NSString * const MTRSetupPayloadCodingKeyRendevouzInformation = @"MTRSP.ck.rendezvousFlags"; static NSString * const MTRSetupPayloadCodingKeyHasShortDiscriminator = @"MTRSP.ck.hasShortDiscriminator"; static NSString * const MTRSetupPayloadCodingKeyDiscriminator = @"MTRSP.ck.discriminator"; static NSString * const MTRSetupPayloadCodingKeySetupPasscode = @"MTRSP.ck.setupPINCode"; static NSString * const MTRSetupPayloadCodingKeySerialNumber = @"MTRSP.ck.serialNumber"; +static NSString * const MTRSetupPayloadCodingKeyQRCode = @"qr"; + (BOOL)supportsSecureCoding { @@ -285,186 +555,148 @@ + (BOOL)supportsSecureCoding - (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:[self qrCodeStringSkippingValidation:YES] forKey:MTRSetupPayloadCodingKeyQRCode]; [coder encodeObject:self.version forKey:MTRSetupPayloadCodingKeyVersion]; [coder encodeObject:self.vendorID forKey:MTRSetupPayloadCodingKeyVendorID]; [coder encodeObject:self.productID forKey:MTRSetupPayloadCodingKeyProductID]; - // Casts are safe because commissioning flow, discoveryCapabilities, and - // hasShortDiscriminator values are all pretty small and non-negative. - [coder encodeInteger:static_cast(self.commissioningFlow) forKey:MTRSetupPayloadCodingKeyCommissioningFlow]; - // We used to encode the discovery capabilities as an NSNumber object, with - // nil representing "unknown". Keep doing that, for backwards compat. - [coder encodeObject:[MTRSetupPayload _boxDiscoveryCapabilities:self.discoveryCapabilities] - forKey:MTRSetupPayloadCodingKeyDiscoveryCapabilities]; - [coder encodeInteger:static_cast(self.hasShortDiscriminator) forKey:MTRSetupPayloadCodingKeyHasShortDiscriminator]; + [coder encodeInteger:self.commissioningFlow forKey:MTRSetupPayloadCodingKeyCommissioningFlow]; + // For compatibility reasons, keep encoding rendevouzInformation instead of discoveryCapabilities + [coder encodeObject:self.rendezvousInformation forKey:MTRSetupPayloadCodingKeyRendevouzInformation]; + [coder encodeInteger:(self.hasShortDiscriminator ? 1 : 0) forKey:MTRSetupPayloadCodingKeyHasShortDiscriminator]; [coder encodeObject:self.discriminator forKey:MTRSetupPayloadCodingKeyDiscriminator]; [coder encodeObject:self.setupPasscode forKey:MTRSetupPayloadCodingKeySetupPasscode]; [coder encodeObject:self.serialNumber forKey:MTRSetupPayloadCodingKeySerialNumber]; } -- (instancetype _Nullable)initWithCoder:(NSCoder *)decoder -{ - NSNumber * version = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyVersion]; - NSNumber * vendorID = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyVendorID]; - NSNumber * productID = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyProductID]; - NSInteger commissioningFlow = [decoder decodeIntegerForKey:MTRSetupPayloadCodingKeyCommissioningFlow]; - MTRDiscoveryCapabilities discoveryCapabilities = - [MTRSetupPayload _unboxDiscoveryCapabilities:[decoder decodeObjectOfClass:[NSNumber class] - forKey:MTRSetupPayloadCodingKeyDiscoveryCapabilities]]; - NSInteger hasShortDiscriminator = [decoder decodeIntegerForKey:MTRSetupPayloadCodingKeyHasShortDiscriminator]; - NSNumber * discriminator = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeyDiscriminator]; - NSNumber * setupPasscode = [decoder decodeObjectOfClass:[NSNumber class] forKey:MTRSetupPayloadCodingKeySetupPasscode]; - NSString * serialNumber = [decoder decodeObjectOfClass:[NSString class] forKey:MTRSetupPayloadCodingKeySerialNumber]; - - MTRSetupPayload * payload = [[MTRSetupPayload alloc] init]; - payload.version = version; - payload.vendorID = vendorID; - payload.productID = productID; - payload.commissioningFlow = static_cast(commissioningFlow); - payload.discoveryCapabilities = discoveryCapabilities; - payload.hasShortDiscriminator = static_cast(hasShortDiscriminator); - payload.discriminator = discriminator; - payload.setupPasscode = setupPasscode; - payload.serialNumber = serialNumber; - - return payload; -} - -- (NSString * _Nullable)manualEntryCode +- (instancetype)initWithCoder:(NSCoder *)coder { - CHIP_ERROR err = CHIP_NO_ERROR; - std::string outDecimalString; - chip::SetupPayload payload; + self = [super init]; - /// The 11 digit manual pairing code only requires the version, VID_PID present flag, - /// discriminator, and the setup pincode. - payload.version = [self.version unsignedCharValue]; - if (self.hasShortDiscriminator) { - payload.discriminator.SetShortValue([self.discriminator unsignedCharValue]); + // We can't rely on the QR code to be present because older versions of this class + // did not encode it. When present, it carries almost the entire state of the object. + NSString * qrCode = [coder decodeObjectOfClass:NSString.class forKey:MTRSetupPayloadCodingKeyQRCode]; + if (qrCode != nil) { + [self initializeFromQRCode:qrCode]; } else { - payload.discriminator.SetLongValue([self.discriminator unsignedShortValue]); + self.version = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeyVersion]; + self.vendorID = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeyVendorID]; + self.productID = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeyProductID]; + self.commissioningFlow = static_cast([coder decodeIntegerForKey:MTRSetupPayloadCodingKeyCommissioningFlow]); + self.setupPasscode = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeySetupPasscode]; + self.serialNumber = [coder decodeObjectOfClass:NSString.class forKey:MTRSetupPayloadCodingKeySerialNumber]; } - payload.setUpPINCode = [self.setupPasscode unsignedIntValue]; - err = chip::ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(outDecimalString); + // The QR code cannot represent short discriminators or the absence of rendevouz + // information, so always decode the state of those properties separately. + self.hasShortDiscriminator = ([coder decodeIntegerForKey:MTRSetupPayloadCodingKeyHasShortDiscriminator] != 0); + self.discriminator = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeyDiscriminator]; + // For compatibility reasons, keep decoding rendevouzInformation instead of discoveryCapabilities + self.rendezvousInformation = [coder decodeObjectOfClass:NSNumber.class forKey:MTRSetupPayloadCodingKeyRendevouzInformation]; - if (err != CHIP_NO_ERROR) { - return nil; - } - - return [NSString stringWithUTF8String:outDecimalString.c_str()]; + return self; } -- (NSString * _Nullable)qrCodeString:(NSError * __autoreleasing *)error +#pragma mark - Utility class methods + ++ (NSUInteger)generateRandomPIN { - if (self.commissioningFlow == MTRCommissioningFlowInvalid) { - // No idea how to map this to the standard codes. - if (error != nil) { - *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE logContext:@"invalid flow"]; + do { + // Make sure the thing we generate is in the right range. + uint32_t setupPIN = arc4random_uniform(chip::kSetupPINCodeMaximumValue) + 1; + if (chip::SetupPayload::IsValidSetupPIN(setupPIN)) { + return setupPIN; } - return nil; - } - if (self.hasShortDiscriminator) { - // Can't create a QR code with a short discriminator. - if (error != nil) { - *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE logContext:@"cannot create a QR code with a short descrimintor"]; - } - return nil; - } + // We got pretty unlikely with our random number generation. Just try + // again. The chance that this loop does not terminate in a reasonable + // amount of time is astronomically low, assuming arc4random_uniform is not + // broken. + } while (true); +} - if (self.discoveryCapabilities == MTRDiscoveryCapabilitiesUnknown) { - // Can't create a QR code if we don't know the discovery capabilities. - if (error != nil) { - *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE logContext:@"cannot create a QR code with unknown discovery capabilities"]; - } - return nil; - } ++ (NSNumber *)generateRandomSetupPasscode +{ + return @([self generateRandomPIN]); +} - chip::SetupPayload payload; - - payload.version = [self.version unsignedCharValue]; - payload.vendorID = [self.vendorID unsignedShortValue]; - payload.productID = [self.productID unsignedShortValue]; - payload.commissioningFlow = [MTRSetupPayload unconvertCommissioningFlow:self.commissioningFlow]; - payload.rendezvousInformation = [MTRSetupPayload convertDiscoveryCapabilities:self.discoveryCapabilities]; - payload.discriminator.SetLongValue([self.discriminator unsignedShortValue]); - payload.setUpPINCode = [self.setupPasscode unsignedIntValue]; - if (self.serialNumber != nil) { - CHIP_ERROR err = payload.addSerialNumber(self.serialNumber.UTF8String); - if (err != CHIP_NO_ERROR) { - if (error != nil) { - *error = [MTRError errorForCHIPErrorCode:err]; - } - return nil; - } - } +@end - std::string outQRCodeString; - CHIP_ERROR err = chip::QRCodeSetupPayloadGenerator(payload).payloadBase38RepresentationWithAutoTLVBuffer(outQRCodeString); +MTR_DIRECT_MEMBERS +@implementation MTROptionalQRCodeInfo (Deprecated) - if (err != CHIP_NO_ERROR) { - if (error != nil) { - *error = [MTRError errorForCHIPErrorCode:err]; - } - return nil; - } +- (instancetype)init +{ + return [self initWithTag:@0xff stringValue:@""]; +} - return [NSString stringWithUTF8String:outQRCodeString.c_str()]; +- (void)setType:(MTROptionalQRCodeInfoType)type +{ + /* ignored */ } -+ (nullable NSNumber *)_boxDiscoveryCapabilities:(MTRDiscoveryCapabilities)discoveryCapabilities +- (void)setTag:(NSNumber *)tag { - if (discoveryCapabilities == MTRDiscoveryCapabilitiesUnknown) { - return nil; - } + /* ignored */ +} - return @(discoveryCapabilities); +- (NSNumber *)infoType +{ + return @(self.type); } -+ (MTRDiscoveryCapabilities)_unboxDiscoveryCapabilities:(nullable NSNumber *)boxedDiscoveryCapabilities +- (void)setInfoType:(NSNumber *)infoType { - if (boxedDiscoveryCapabilities == nil) { - return MTRDiscoveryCapabilitiesUnknown; - } + /* ignored */ +} - NSUInteger value = [boxedDiscoveryCapabilities unsignedIntegerValue]; - if (value == MTRDiscoveryCapabilitiesUnknown) { - // The discovery capabilities were actually known - // (rendezvousInformation is not nil), and must support on-network. - return MTRDiscoveryCapabilitiesOnNetwork; - } +- (void)setIntegerValue:(NSNumber *)integerValue +{ + /* ignored */ +} - return static_cast(value); +- (void)setStringValue:(NSString *)stringValue +{ + /* ignored */ } @end MTR_DIRECT_MEMBERS -@implementation MTROptionalQRCodeInfo (Deprecated) +@implementation MTRSetupPayload (Deprecated) -- (NSNumber *)infoType +- (instancetype)init { - return @(self.type); + return [super init]; // a default-constructed SetupPayload is fine here } -- (void)setInfoType:(NSNumber *)infoType ++ (instancetype)new { - self.type = static_cast([infoType unsignedIntegerValue]); + return [super new]; } -@end - -MTR_DIRECT_MEMBERS -@implementation MTRSetupPayload (Deprecated) ++ (MTRSetupPayload * _Nullable)setupPayloadWithOnboardingPayload:(NSString *)onboardingPayload + error:(NSError * __autoreleasing *)error +{ + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithPayload:onboardingPayload]; + if (!payload && error) { + *error = [MTRError errorWithCode:MTRErrorCodeInvalidArgument]; + } + return payload; +} - (nullable NSNumber *)rendezvousInformation { - return [MTRSetupPayload _boxDiscoveryCapabilities:self.discoveryCapabilities]; + auto value = self.discoveryCapabilities; + return (value != MTRDiscoveryCapabilitiesUnknown) ? @(value) : nil; } - (void)setRendezvousInformation:(nullable NSNumber *)rendezvousInformation { - self.discoveryCapabilities = [MTRSetupPayload _unboxDiscoveryCapabilities:rendezvousInformation]; + if (rendezvousInformation != nil) { + self.discoveryCapabilities = KnownDiscoveryCapabilities(rendezvousInformation.unsignedIntegerValue); + } else { + self.discoveryCapabilities = MTRDiscoveryCapabilitiesUnknown; + } } - (NSNumber *)setUpPINCode @@ -477,26 +709,18 @@ - (void)setSetUpPINCode:(NSNumber *)setUpPINCode self.setupPasscode = setUpPINCode; } -- (instancetype)init +- (nullable NSString *)qrCodeString:(NSError * __autoreleasing _Nullable *)error { - if (self = [super init]) { - _version = @(0); // Only supported Matter version so far. - _vendorID = @(0); // Not available. - _productID = @(0); // Not available. - _commissioningFlow = MTRCommissioningFlowStandard; - _discoveryCapabilities = MTRDiscoveryCapabilitiesUnknown; - _hasShortDiscriminator = NO; - _discriminator = @(0); - _setupPasscode = @(11111111); // Invalid passcode - _serialNumber = nil; + NSString * result = [self qrCodeString]; + if (!result && error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; } - - return self; + return result; } -+ (instancetype)new +- (NSArray *)getAllOptionalVendorData:(NSError * __autoreleasing *)error { - return [[self alloc] init]; + return self.vendorElements; // never actually fails } @end diff --git a/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h b/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h index a119a4b6e2059f..5e14ce025c8f73 100644 --- a/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h +++ b/src/darwin/Framework/CHIP/MTRSetupPayload_Internal.h @@ -19,18 +19,17 @@ #import "MTRDefines_Internal.h" -#ifdef __cplusplus -#import #import -#endif + +NS_ASSUME_NONNULL_BEGIN MTR_DIRECT_MEMBERS @interface MTRSetupPayload () -#ifdef __cplusplus - (instancetype)initWithSetupPayload:(chip::SetupPayload)setupPayload; -- (MTRDiscoveryCapabilities)convertRendezvousFlags:(const chip::Optional &)value; -- (MTRCommissioningFlow)convertCommissioningFlow:(chip::CommissioningFlow)value; -#endif +- (nullable instancetype)initWithQRCode:(NSString *)qrCodePayload; +- (nullable instancetype)initWithManualPairingCode:(NSString *)manualCode; @end + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRUtilities.h b/src/darwin/Framework/CHIP/MTRUtilities.h new file mode 100644 index 00000000000000..754f5da7ecadd6 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRUtilities.h @@ -0,0 +1,27 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Calls `-[NSObject isEqual:]` but returns YES when comparing nil to nil. + */ +MTR_EXTERN BOOL MTREqualObjects(id _Nullable a, id _Nullable b); + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRUtilities.mm b/src/darwin/Framework/CHIP/MTRUtilities.mm new file mode 100644 index 00000000000000..de85b498626495 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRUtilities.mm @@ -0,0 +1,23 @@ +/** + * + * Copyright (c) 2024 Project CHIP Authors + * + * 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. + */ + +#import "MTRUtilities.h" + +BOOL MTREqualObjects(id _Nullable a, id _Nullable b) +{ + return (a == nil) ? (b == nil) : [a isEqual:b]; +} diff --git a/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m b/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m index 7060c3ba11599c..6f53305f943a69 100644 --- a/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m +++ b/src/darwin/Framework/CHIPTests/MTRSetupPayloadTests.m @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,8 @@ - (void)testOnboardingPayloadParser_Manual_NoError XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowCustom); XCTAssertEqual(payload.version.unsignedIntegerValue, 0); XCTAssertEqual(payload.discoveryCapabilities, MTRDiscoveryCapabilitiesUnknown); + + XCTAssertEqualObjects(payload.manualEntryCode, @"641286075300001000016"); } - (void)testOnboardingPayloadParser_QRCode_NoError @@ -90,31 +92,13 @@ - (void)testOnboardingPayloadParser_NFC_NoError XCTAssertEqual(payload.discoveryCapabilities, MTRDiscoveryCapabilitiesSoftAP); } -- (void)testManualParser -{ - NSError * error; - MTRSetupPayload * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:@"641286075300001000016" error:&error]; - - XCTAssertNotNil(payload); - XCTAssertNil(error); - - XCTAssertTrue(payload.hasShortDiscriminator); - XCTAssertEqual(payload.discriminator.unsignedIntegerValue, 10); - XCTAssertEqual(payload.setupPasscode.unsignedIntegerValue, 12345670); - XCTAssertEqual(payload.vendorID.unsignedIntegerValue, 1); - XCTAssertEqual(payload.productID.unsignedIntegerValue, 1); - XCTAssertEqual(payload.commissioningFlow, MTRCommissioningFlowCustom); - XCTAssertEqual(payload.version.unsignedIntegerValue, 0); - XCTAssertEqual(payload.discoveryCapabilities, MTRDiscoveryCapabilitiesUnknown); -} - - (void)testManualParser_Error { NSError * error; MTRSetupPayload * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:@"" error:&error]; XCTAssertNil(payload); - XCTAssertEqual(error.code, MTRErrorCodeInvalidStringLength); + XCTAssertNotNil(error); } - (void)testQRCodeParser_Error @@ -123,7 +107,7 @@ - (void)testQRCodeParser_Error MTRSetupPayload * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:@"MT:M5L90MP500K64J0000." error:&error]; XCTAssertNil(payload); - XCTAssertEqual(error.code, MTRErrorCodeInvalidArgument); + XCTAssertNotNil(error); } - (void)testQRCodeParser @@ -178,6 +162,62 @@ - (void)testQRCodeParserWithOptionalData XCTAssertEqual(info.integerValue.intValue, 12); } } + + // Test access by tag + XCTAssertEqualObjects([payload vendorElementWithTag:@130].stringValue, @"myData"); + XCTAssertEqualObjects([payload vendorElementWithTag:@131].integerValue, @12); +} + +- (void)testAddVendorElement +{ + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithSetupPasscode:@314159 discriminator:@555]; + XCTAssertEqual(payload.vendorElements.count, 0); + [payload addOrReplaceVendorElement:[[MTROptionalQRCodeInfo alloc] initWithTag:@0xff int32Value:42]]; + XCTAssertEqual(payload.vendorElements.count, 1); + XCTAssertEqualObjects(payload.vendorElements.firstObject.integerValue, @42); + XCTAssertEqualObjects([payload vendorElementWithTag:@0xff].integerValue, @42); +} + +- (void)testVendorElementsEncodedToQRCode +{ + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithSetupPasscode:@314159 discriminator:@555]; + [payload addOrReplaceVendorElement:[[MTROptionalQRCodeInfo alloc] initWithTag:@0x80 stringValue:@"Hello"]]; + MTRSetupPayload * decoded = [[MTRSetupPayload alloc] initWithPayload:payload.qrCodeString]; + XCTAssertNotNil(decoded); + XCTAssertEqualObjects([decoded vendorElementWithTag:@0x80].stringValue, @"Hello"); +} + +- (void)testRemoveVendorElements +{ + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithPayload:@"MT:M5L90MP500K64J0A33P0SET70.QT52B.E23-WZE0WISA0DK5N1K8SQ1RYCU1O0"]; + XCTAssertNotNil(payload); + XCTAssertEqual(payload.vendorElements.count, 2); + [payload removeVendorElementWithTag:@128]; // no change, no vendor element present with this tag + XCTAssertEqual(payload.vendorElements.count, 2); + [payload removeVendorElementWithTag:@130]; + XCTAssertEqual(payload.vendorElements.count, 1); + [payload removeVendorElementWithTag:@131]; + XCTAssertEqual(payload.vendorElements.count, 0); +} + +- (void)testQrCodeInfoCopyAndEquality +{ + MTROptionalQRCodeInfo * a = [[MTROptionalQRCodeInfo alloc] initWithTag:@0x88 stringValue:@"hello"]; + MTROptionalQRCodeInfo * b = [[MTROptionalQRCodeInfo alloc] initWithTag:@0x88 stringValue:@"hello"]; + MTROptionalQRCodeInfo * c = [[MTROptionalQRCodeInfo alloc] initWithTag:@0xff stringValue:@"hello"]; + MTROptionalQRCodeInfo * d = [[MTROptionalQRCodeInfo alloc] initWithTag:@0x88 int32Value:42]; + MTROptionalQRCodeInfo * e = [[MTROptionalQRCodeInfo alloc] initWithTag:@0x88 int32Value:0xbad]; + XCTAssertTrue([a isEqual:a]); + XCTAssertTrue([a isEqual:[a copy]]); + XCTAssertTrue([a isEqual:b]); + XCTAssertTrue([a isEqual:[b copy]]); + XCTAssertEqual(a.hash, b.hash); + XCTAssertEqual(a.hash, [[a copy] hash]); + XCTAssertFalse([a isEqual:nil]); + XCTAssertFalse([a isEqual:c]); + XCTAssertFalse([a isEqual:d]); + XCTAssertFalse([a isEqual:e]); + XCTAssertFalse([d isEqual:e]); } - (void)testQRCodeWithNoCapabilities @@ -198,7 +238,7 @@ - (void)testQRCodeWithNoCapabilities XCTAssertEqual(payload.discoveryCapabilities, MTRDiscoveryCapabilitiesOnNetwork); } -- (void)testQRCodePropertyAliases +- (void)testDeprecatedPropertyAliases { NSError * error; MTRSetupPayload * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:@"MT:M5L9000000K64J00000" error:&error]; @@ -294,6 +334,9 @@ - (void)testSecureCodingRoundtrip ]) { MTRSetupPayload * payload = [MTRSetupPayload setupPayloadWithOnboardingPayload:string error:&error]; XCTAssertNotNil(payload, @"Error: %@", error); + // Ensure our test data has discriminator values that make for the most meaningful round-trip tests. + XCTAssert(payload.discriminator.integerValue != 0); + XCTAssert(payload.hasShortDiscriminator || payload.discriminator.integerValue > 0xf); [payloads addObject:payload]; } @@ -301,7 +344,14 @@ - (void)testSecureCodingRoundtrip [payloads addObject:[[MTRSetupPayload alloc] init]]; [payloads addObject:[[MTRSetupPayload alloc] initWithSetupPasscode:@22222222 discriminator:@42]]; + MTRSetupPayload * futureValues = [[MTRSetupPayload alloc] initWithSetupPasscode:@314159 discriminator:@555]; + futureValues.commissioningFlow = 3; // reserved in the spec + futureValues.discoveryCapabilities = 0x84; // bits 3-7 reserved in the spec + [payloads addObject:futureValues]; + for (MTRSetupPayload * payload in payloads) { + NSLog(@"Payload: %@", payload); + NSData * data = [NSKeyedArchiver archivedDataWithRootObject:payload requiringSecureCoding:YES error:&error]; XCTAssertNotNil(data, @"Error: %@", error); MTRSetupPayload * decoded = [NSKeyedUnarchiver unarchivedObjectOfClass:MTRSetupPayload.class fromData:data error:&error]; @@ -322,18 +372,16 @@ - (void)testSecureCodingRoundtrip NSArray * decodedVDs = [decoded getAllOptionalVendorData:&error]; XCTAssertNotNil(decodedVDs, @"Error: %@", error); -#if 0 // TODO: Encode / decode optional vendor data - // MTROptionalQRCodeInfo does not implement isEqual (yet) XCTAssertEqual(decodedVDs.count, payloadVDs.count); - for (int i = 0; i < decodedVDs.count; i++){ + for (int i = 0; i < decodedVDs.count; i++) { MTROptionalQRCodeInfo * decodedVD = decodedVDs[i]; MTROptionalQRCodeInfo * payloadVD = payloadVDs[i]; XCTAssertEqual(decodedVD.type, payloadVD.type); XCTAssertEqualObjects(decodedVD.tag, payloadVD.tag); XCTAssertEqualObjects(decodedVD.integerValue, payloadVD.integerValue); XCTAssertEqualObjects(decodedVD.stringValue, payloadVD.stringValue); + XCTAssertEqualObjects(decodedVD, payloadVD); // also check with isEqual: } -#endif // Note that we can't necessarily expect the manualEntryCode and qrCode strings // we generate here to match the original string, but we should get the same @@ -343,4 +391,52 @@ - (void)testSecureCodingRoundtrip } } +- (void)testCopyingAndEquality +{ + MTRSetupPayload * payload = [[MTRSetupPayload alloc] initWithPayload:@"MT:M5L9000000K64J00000"]; + XCTAssertFalse(payload.hasShortDiscriminator); // came from a QR code + XCTAssert(payload.discriminator.integerValue > 0xf); // can't "accidentally" round-trip through a short discriminator + + MTRSetupPayload * copy = [payload copy]; + XCTAssertNotIdentical(payload, copy); // MTRSetupPayload is mutable, must be a new object + + XCTAssertTrue([payload isEqual:copy]); + XCTAssertTrue([copy isEqual:payload]); + XCTAssertEqual(payload.hash, copy.hash); + + copy.hasShortDiscriminator = YES; + XCTAssertFalse([copy isEqual:payload]); + copy.hasShortDiscriminator = NO; + XCTAssertTrue([copy isEqual:payload]); + XCTAssertEqual(payload.hash, copy.hash); + + MTROptionalQRCodeInfo * element = [[MTROptionalQRCodeInfo alloc] initWithTag:@0x80 stringValue:@"To infinity and beyond!"]; + [copy addOrReplaceVendorElement:element]; + XCTAssertFalse([copy isEqual:payload]); + [payload addOrReplaceVendorElement:element]; + XCTAssertTrue([copy isEqual:payload]); + XCTAssertEqual(payload.hash, copy.hash); + + copy.serialNumber = @"555-123"; + XCTAssertFalse([copy isEqual:payload]); + payload.serialNumber = @"555-123"; + XCTAssertTrue([copy isEqual:payload]); + XCTAssertEqual(payload.hash, copy.hash); +} + +- (void)testCanParseFutureDiscoveryMethod +{ + // We must be able to process QR codes that include discovery methods we don't understand yet + XCTAssertEqual([[MTRSetupPayload alloc] initWithPayload:@"MT:000002VDK3VHMR49000"].discoveryCapabilities, 0x84); + XCTAssertEqual([[MTRSetupPayload alloc] initWithPayload:@"MT:-24J0Q.C.0KA0648G00"].discoveryCapabilities, 0xfa); +} + +- (void)testDescriptionShowsUnknownDiscoveryMethods +{ + MTRSetupPayload * a = [[MTRSetupPayload alloc] initWithSetupPasscode:@888 discriminator:@555]; + MTRSetupPayload * b = [a copy]; + b.discoveryCapabilities |= 0x80; + XCTAssertNotEqualObjects(a.description, b.description); +} + @end diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index be1712972895fb..4cb4edf4a8edd3 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -109,6 +109,8 @@ 3D0C484B29DA4FA0006D811F /* MTRErrorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D0C484A29DA4FA0006D811F /* MTRErrorTests.m */; }; 3D3928D72BBCEA3D00CDEBB2 /* MTRAvailabilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D3928D62BBCEA3D00CDEBB2 /* MTRAvailabilityTests.m */; settings = {COMPILER_FLAGS = "-UMTR_NO_AVAILABILITY -Wno-unguarded-availability-new"; }; }; 3D4733AF2BDF1B80003DC19B /* MTRSetupPayloadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D4733AE2BDF1B80003DC19B /* MTRSetupPayloadTests.m */; }; + 3D4733B32BE2D1DA003DC19B /* MTRUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D4733B22BE2D1CF003DC19B /* MTRUtilities.h */; }; + 3D4733B52BE2D3D7003DC19B /* MTRUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3D4733B42BE2D3D1003DC19B /* MTRUtilities.mm */; }; 3D69868529383096007314E7 /* com.csa.matter.plist in Copy Logging Preferences */ = {isa = PBXBuildFile; fileRef = 3D69868029382EF4007314E7 /* com.csa.matter.plist */; }; 3D843711294977000070D20A /* NSStringSpanConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D84370E294977000070D20A /* NSStringSpanConversion.h */; }; 3D843712294977000070D20A /* MTRCallbackBridgeBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D84370F294977000070D20A /* MTRCallbackBridgeBase.h */; }; @@ -500,6 +502,8 @@ 3D0C484A29DA4FA0006D811F /* MTRErrorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRErrorTests.m; sourceTree = ""; }; 3D3928D62BBCEA3D00CDEBB2 /* MTRAvailabilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRAvailabilityTests.m; sourceTree = ""; }; 3D4733AE2BDF1B80003DC19B /* MTRSetupPayloadTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRSetupPayloadTests.m; sourceTree = ""; }; + 3D4733B22BE2D1CF003DC19B /* MTRUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRUtilities.h; sourceTree = ""; }; + 3D4733B42BE2D3D1003DC19B /* MTRUtilities.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRUtilities.mm; sourceTree = ""; }; 3D69868029382EF4007314E7 /* com.csa.matter.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.csa.matter.plist; sourceTree = ""; }; 3D84370E294977000070D20A /* NSStringSpanConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSStringSpanConversion.h; sourceTree = ""; }; 3D84370F294977000070D20A /* MTRCallbackBridgeBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRCallbackBridgeBase.h; sourceTree = ""; }; @@ -1355,6 +1359,8 @@ 997DED152695343400975E97 /* MTRThreadOperationalDataset.mm */, 51C659D72BA3787500C54922 /* MTRTimeUtils.h */, 51C659D82BA3787500C54922 /* MTRTimeUtils.mm */, + 3D4733B22BE2D1CF003DC19B /* MTRUtilities.h */, + 3D4733B42BE2D3D1003DC19B /* MTRUtilities.mm */, 3D843710294977000070D20A /* NSDataSpanConversion.h */, 3D84370E294977000070D20A /* NSStringSpanConversion.h */, 5117DD3729A931AE00FFA1AA /* MTROperationalBrowser.h */, @@ -1643,6 +1649,7 @@ 514C7A022B64223400DD6D7B /* MTRServerEndpoint_Internal.h in Headers */, 511913FC28C100EF009235E9 /* MTRBaseSubscriptionCallback.h in Headers */, 51565CB12A7AD77600469F18 /* MTRDeviceControllerDataStore.h in Headers */, + 3D4733B32BE2D1DA003DC19B /* MTRUtilities.h in Headers */, 3D843713294977000070D20A /* NSDataSpanConversion.h in Headers */, 991DC08B247704DC00C13860 /* MTRLogging_Internal.h in Headers */, 51FE723F2ACDEF3E00437032 /* MTRCommandPayloadExtensions_Internal.h in Headers */, @@ -1893,6 +1900,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3D4733B52BE2D3D7003DC19B /* MTRUtilities.mm in Sources */, 2C8C8FC2253E0C2100797F05 /* MTRPersistentStorageDelegateBridge.mm in Sources */, 99AECC802798A57F00B6355B /* MTRCommissioningParameters.mm in Sources */, 2CB7163C252E8A7C0026E2BB /* MTRDeviceControllerDelegateBridge.mm in Sources */, From cfbcf1e69715a585b02bea80dd14823375566afc Mon Sep 17 00:00:00 2001 From: feasel <120589145+feasel0@users.noreply.github.com> Date: Fri, 10 May 2024 10:54:36 -0400 Subject: [PATCH 34/39] Converted unit tests in src/tracing/tests from NL to PW. (#33390) * Updated unit tests in tracing/tests to use PW instead of NL. * Fixed the condition that enables tracing tests. It was "mutliplexed" but that has since been replaced by a full path. * Remove TracingTests from test_components.txt --- src/BUILD.gn | 2 +- src/tracing/tests/BUILD.gn | 5 +- src/tracing/tests/TestMetricEvents.cpp | 256 ++++++++++--------------- src/tracing/tests/TestTracing.cpp | 41 ++-- 4 files changed, 118 insertions(+), 186 deletions(-) diff --git a/src/BUILD.gn b/src/BUILD.gn index d1dfcc7856135e..01aae8abc3fbab 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -106,7 +106,7 @@ if (chip_build_tests) { ] if (matter_enable_tracing_support && - matter_trace_config == "multiplexed") { + matter_trace_config == "${chip_root}/src/tracing/multiplexed") { tests += [ "${chip_root}/src/tracing/tests" ] } } diff --git a/src/tracing/tests/BUILD.gn b/src/tracing/tests/BUILD.gn index 8f28b56ecb890c..f6b4f132255af0 100644 --- a/src/tracing/tests/BUILD.gn +++ b/src/tracing/tests/BUILD.gn @@ -19,8 +19,9 @@ import("//build_overrides/nlunit_test.gni") import("${chip_root}/build/chip/chip_test_suite.gni") import("${chip_root}/src/tracing/tracing_args.gni") -if (matter_enable_tracing_support && matter_trace_config == "multiplexed") { - chip_test_suite_using_nltest("tests") { +if (matter_enable_tracing_support && + matter_trace_config == "${chip_root}/src/tracing/multiplexed") { + chip_test_suite("tests") { output_name = "libTracingTests" test_sources = [ diff --git a/src/tracing/tests/TestMetricEvents.cpp b/src/tracing/tests/TestMetricEvents.cpp index 72e159df7cf7fa..916a002d9f78b9 100644 --- a/src/tracing/tests/TestMetricEvents.cpp +++ b/src/tracing/tests/TestMetricEvents.cpp @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #include #include -#include - #include #include #include @@ -74,56 +73,56 @@ class MetricEventBackend : public Backend std::vector mMetricEvents; }; -void TestBasicMetricEvent(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestBasicMetricEvent) { { MetricEvent event(MetricEvent::Type::kInstantEvent, "instant_event"); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kInstantEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("instant_event")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined); + EXPECT_EQ(event.type(), MetricEvent::Type::kInstantEvent); + EXPECT_EQ(std::string(event.key()), std::string("instant_event")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined); } { MetricEvent event(MetricEvent::Type::kBeginEvent, "begin_event"); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kBeginEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("begin_event")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined); + EXPECT_EQ(event.type(), MetricEvent::Type::kBeginEvent); + EXPECT_EQ(std::string(event.key()), std::string("begin_event")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined); } { MetricEvent event(MetricEvent::Type::kEndEvent, "end_event"); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUndefined); + EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent); + EXPECT_EQ(std::string(event.key()), std::string("end_event")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUndefined); } { MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_int32_value", int32_t(42)); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_int32_value")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kInt32); - NL_TEST_ASSERT(inSuite, event.ValueInt32() == 42); + EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent); + EXPECT_EQ(std::string(event.key()), std::string("end_event_with_int32_value")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kInt32); + EXPECT_EQ(event.ValueInt32(), 42); } { MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_uint32_value", uint32_t(42)); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_uint32_value")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kUInt32); - NL_TEST_ASSERT(inSuite, event.ValueUInt32() == 42u); + EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent); + EXPECT_EQ(std::string(event.key()), std::string("end_event_with_uint32_value")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kUInt32); + EXPECT_EQ(event.ValueUInt32(), 42u); } { MetricEvent event(MetricEvent::Type::kEndEvent, "end_event_with_error_value", CHIP_ERROR_BUSY); - NL_TEST_ASSERT(inSuite, event.type() == MetricEvent::Type::kEndEvent); - NL_TEST_ASSERT(inSuite, std::string(event.key()) == std::string("end_event_with_error_value")); - NL_TEST_ASSERT(inSuite, event.ValueType() == MetricEvent::Value::Type::kChipErrorCode); - NL_TEST_ASSERT(inSuite, chip::ChipError(event.ValueErrorCode()) == CHIP_ERROR_BUSY); + EXPECT_EQ(event.type(), MetricEvent::Type::kEndEvent); + EXPECT_EQ(std::string(event.key()), std::string("end_event_with_error_value")); + EXPECT_EQ(event.ValueType(), MetricEvent::Value::Type::kChipErrorCode); + EXPECT_EQ(chip::ChipError(event.ValueErrorCode()), CHIP_ERROR_BUSY); } } -void TestInstantMetricEvent(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestInstantMetricEvent) { MetricEventBackend backend; @@ -141,12 +140,11 @@ void TestInstantMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event3"), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -void TestBeginEndMetricEvent(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestBeginEndMetricEvent) { MetricEventBackend backend1; MetricEventBackend backend2; @@ -168,9 +166,8 @@ void TestBeginEndMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kEndEvent, "event1"), }; - NL_TEST_ASSERT(inSuite, backend1.GetMetricEvents().size() == expected1.size()); - NL_TEST_ASSERT( - inSuite, + EXPECT_EQ(backend1.GetMetricEvents().size(), expected1.size()); + EXPECT_TRUE( std::equal(backend1.GetMetricEvents().begin(), backend1.GetMetricEvents().end(), expected1.begin(), expected1.end())); { @@ -197,14 +194,13 @@ void TestBeginEndMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kEndEvent, "event4"), }; - NL_TEST_ASSERT(inSuite, backend2.GetMetricEvents().size() == expected2.size()); - NL_TEST_ASSERT( - inSuite, + EXPECT_EQ(backend2.GetMetricEvents().size(), expected2.size()); + EXPECT_TRUE( std::equal(backend2.GetMetricEvents().begin(), backend2.GetMetricEvents().end(), expected2.begin(), expected2.end())); } } -void TestScopedMetricEvent(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestScopedMetricEvent) { MetricEventBackend backend1; MetricEventBackend backend2; @@ -247,9 +243,8 @@ void TestScopedMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kEndEvent, "event1", CHIP_ERROR_BUSY), }; - NL_TEST_ASSERT(inSuite, backend1.GetMetricEvents().size() == expected1.size()); - NL_TEST_ASSERT( - inSuite, + EXPECT_EQ(backend1.GetMetricEvents().size(), expected1.size()); + EXPECT_TRUE( std::equal(backend1.GetMetricEvents().begin(), backend1.GetMetricEvents().end(), expected1.begin(), expected1.end())); std::vector expected2 = { @@ -261,9 +256,8 @@ void TestScopedMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kEndEvent, "event2", CHIP_ERROR_BAD_REQUEST), }; - NL_TEST_ASSERT(inSuite, backend2.GetMetricEvents().size() == expected2.size()); - NL_TEST_ASSERT( - inSuite, + EXPECT_EQ(backend2.GetMetricEvents().size(), expected2.size()); + EXPECT_TRUE( std::equal(backend2.GetMetricEvents().begin(), backend2.GetMetricEvents().end(), expected2.begin(), expected2.end())); std::vector expected3 = { @@ -271,9 +265,8 @@ void TestScopedMetricEvent(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kEndEvent, "event3", CHIP_ERROR_EVENT_ID_FOUND), }; - NL_TEST_ASSERT(inSuite, backend3.GetMetricEvents().size() == expected3.size()); - NL_TEST_ASSERT( - inSuite, + EXPECT_EQ(backend3.GetMetricEvents().size(), expected3.size()); + EXPECT_TRUE( std::equal(backend3.GetMetricEvents().begin(), backend3.GetMetricEvents().end(), expected3.begin(), expected3.end())); } } @@ -283,7 +276,7 @@ static int DoubleOf(int input) return input * 2; } -void TestVerifyOrExitWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestVerifyOrExitWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -297,13 +290,12 @@ void TestVerifyOrExitWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE), }; - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -void TestSuccessOrExitWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestSuccessOrExitWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -318,10 +310,9 @@ void TestSuccessOrExitWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BUSY), }; - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUSY); - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(err, CHIP_ERROR_BUSY); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static CHIP_ERROR InvokeReturnErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error) @@ -330,28 +321,27 @@ static CHIP_ERROR InvokeReturnErrorOnFailureWithMetric(MetricKey key, const CHIP return CHIP_NO_ERROR; } -void TestReturnErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestReturnErrorOnFailureWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); CHIP_ERROR err = InvokeReturnErrorOnFailureWithMetric("event0", CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeReturnErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); + EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE); err = InvokeReturnErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST); + EXPECT_EQ(err, CHIP_ERROR_BAD_REQUEST); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE), MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static CHIP_ERROR InvokeReturnLogErrorOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error) @@ -360,28 +350,27 @@ static CHIP_ERROR InvokeReturnLogErrorOnFailureWithMetric(MetricKey key, const C return CHIP_NO_ERROR; } -void TestReturnLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestReturnLogErrorOnFailureWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); CHIP_ERROR err = InvokeReturnLogErrorOnFailureWithMetric("event0", CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeReturnLogErrorOnFailureWithMetric("event1", CHIP_ERROR_INCORRECT_STATE); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); + EXPECT_EQ(err, CHIP_ERROR_INCORRECT_STATE); err = InvokeReturnLogErrorOnFailureWithMetric("event2", CHIP_ERROR_BAD_REQUEST); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST); + EXPECT_EQ(err, CHIP_ERROR_BAD_REQUEST); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_INCORRECT_STATE), MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static void InvokeReturnOnFailureWithMetric(MetricKey key, const CHIP_ERROR & error) @@ -390,7 +379,7 @@ static void InvokeReturnOnFailureWithMetric(MetricKey key, const CHIP_ERROR & er return; } -void TestReturnOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestReturnOnFailureWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -406,9 +395,8 @@ void TestReturnOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event2", CHIP_ERROR_BAD_REQUEST), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static void InvokeVerifyOrReturnWithMetric(MetricKey key, bool result) @@ -417,7 +405,7 @@ static void InvokeVerifyOrReturnWithMetric(MetricKey key, bool result) return; } -void TestInvokeVerifyOrReturnWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestInvokeVerifyOrReturnWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -432,9 +420,8 @@ void TestInvokeVerifyOrReturnWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static CHIP_ERROR InvokeVerifyOrReturnErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error) @@ -443,31 +430,30 @@ static CHIP_ERROR InvokeVerifyOrReturnErrorWithMetric(MetricKey key, bool expr, return CHIP_NO_ERROR; } -void TestVerifyOrReturnErrorWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestVerifyOrReturnErrorWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); CHIP_ERROR err = InvokeVerifyOrReturnErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_ERROR_BAD_REQUEST); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeVerifyOrReturnErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED); + EXPECT_EQ(err, CHIP_ERROR_ACCESS_DENIED); err = InvokeVerifyOrReturnErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BUSY); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeVerifyOrReturnErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_CANCELLED); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED); + EXPECT_EQ(err, CHIP_ERROR_CANCELLED); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED), MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_CANCELLED), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } template @@ -477,31 +463,30 @@ static return_code_type InvokeVerifyOrReturnValueWithMetric(MetricKey key, bool return return_code_type(); } -void TestVerifyOrReturnValueWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestVerifyOrReturnValueWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); auto retval = InvokeVerifyOrReturnValueWithMetric("event0", DoubleOf(2) == 4, 0); - NL_TEST_ASSERT(inSuite, retval == 0); + EXPECT_EQ(retval, 0); auto err = InvokeVerifyOrReturnValueWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_ACCESS_DENIED); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ACCESS_DENIED); + EXPECT_EQ(err, CHIP_ERROR_ACCESS_DENIED); err = InvokeVerifyOrReturnValueWithMetric("event2", DoubleOf(4) == 8, CHIP_ERROR_BAD_REQUEST); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); retval = InvokeVerifyOrReturnValueWithMetric("event3", DoubleOf(5) == 11, 16); - NL_TEST_ASSERT(inSuite, retval == 16); + EXPECT_EQ(retval, 16); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_ACCESS_DENIED), MetricEvent(MetricEvent::Type::kInstantEvent, "event3", 16), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } static CHIP_ERROR InvokeVerifyOrReturnLogErrorWithMetric(MetricKey key, bool expr, const CHIP_ERROR & error) @@ -510,31 +495,30 @@ static CHIP_ERROR InvokeVerifyOrReturnLogErrorWithMetric(MetricKey key, bool exp return CHIP_NO_ERROR; } -void TestVerifyOrReturnLogErrorWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestVerifyOrReturnLogErrorWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); auto err = InvokeVerifyOrReturnLogErrorWithMetric("event0", DoubleOf(2) == 4, CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeVerifyOrReturnLogErrorWithMetric("event1", DoubleOf(3) == 9, CHIP_ERROR_CANCELLED); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_CANCELLED); + EXPECT_EQ(err, CHIP_ERROR_CANCELLED); err = InvokeVerifyOrReturnLogErrorWithMetric("event2", DoubleOf(4) == 8, CHIP_NO_ERROR); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); err = InvokeVerifyOrReturnLogErrorWithMetric("event3", DoubleOf(5) == 11, CHIP_ERROR_BAD_REQUEST); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BAD_REQUEST); + EXPECT_EQ(err, CHIP_ERROR_BAD_REQUEST); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event1", CHIP_ERROR_CANCELLED), MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BAD_REQUEST), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } template @@ -544,34 +528,33 @@ static return_code_type InvokeReturnErrorCodeWithMetricIf(MetricKey key, bool ex return return_code_type(); } -void TestReturnErrorCodeWithMetricIf(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestReturnErrorCodeWithMetricIf) { MetricEventBackend backend; ScopedRegistration scope(backend); auto err = InvokeReturnErrorCodeWithMetricIf("event0", DoubleOf(2) == 4, CHIP_ERROR_DUPLICATE_KEY_ID); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_DUPLICATE_KEY_ID); + EXPECT_EQ(err, CHIP_ERROR_DUPLICATE_KEY_ID); auto retval = InvokeReturnErrorCodeWithMetricIf("event1", DoubleOf(3) == 9, 11); - NL_TEST_ASSERT(inSuite, retval == 0); + EXPECT_EQ(retval, 0); retval = InvokeReturnErrorCodeWithMetricIf("event2", DoubleOf(4) == 8, 22); - NL_TEST_ASSERT(inSuite, retval == 22); + EXPECT_EQ(retval, 22); err = InvokeReturnErrorCodeWithMetricIf("event3", DoubleOf(5) == 11, CHIP_ERROR_ACCESS_DENIED); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + EXPECT_EQ(err, CHIP_NO_ERROR); std::vector expected = { MetricEvent(MetricEvent::Type::kInstantEvent, "event0", CHIP_ERROR_DUPLICATE_KEY_ID), MetricEvent(MetricEvent::Type::kInstantEvent, "event2", 22), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -void TestExitNowWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestExitNowWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -584,13 +567,12 @@ void TestExitNowWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event0"), }; - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_BUSY); - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(err, CHIP_ERROR_BUSY); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -void TestLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestLogErrorOnFailureWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -606,12 +588,11 @@ void TestLogErrorOnFailureWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event3", CHIP_ERROR_BUSY), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -void TestVerifyOrDoWithMetric(nlTestSuite * inSuite, void * inContext) +TEST(TestMetricEvents, TestVerifyOrDoWithMetric) { MetricEventBackend backend; ScopedRegistration scope(backend); @@ -629,41 +610,8 @@ void TestVerifyOrDoWithMetric(nlTestSuite * inSuite, void * inContext) MetricEvent(MetricEvent::Type::kInstantEvent, "event3", false), }; - NL_TEST_ASSERT(inSuite, backend.GetMetricEvents().size() == expected.size()); - NL_TEST_ASSERT( - inSuite, std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.GetMetricEvents().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.GetMetricEvents().begin(), backend.GetMetricEvents().end(), expected.begin(), expected.end())); } -static const nlTest sMetricTests[] = { - NL_TEST_DEF("BasicMetricEvent", TestBasicMetricEvent), // - NL_TEST_DEF("InstantMetricEvent", TestInstantMetricEvent), // - NL_TEST_DEF("BeginEndMetricEvent", TestBeginEndMetricEvent), // - NL_TEST_DEF("ScopedMetricEvent", TestScopedMetricEvent), // - NL_TEST_DEF("VerifyOrExitWithMetric", TestVerifyOrExitWithMetric), // - NL_TEST_DEF("SuccessOrExitWithMetric", TestSuccessOrExitWithMetric), // - NL_TEST_DEF("ReturnErrorOnFailureWithMetric", TestReturnErrorOnFailureWithMetric), // - NL_TEST_DEF("ReturnLogErrorOnFailureWithMetric", TestReturnLogErrorOnFailureWithMetric), // - NL_TEST_DEF("ReturnOnFailureWithMetric", TestReturnOnFailureWithMetric), // - NL_TEST_DEF("VerifyOrReturnWithMetric", TestInvokeVerifyOrReturnWithMetric), // - NL_TEST_DEF("VerifyOrReturnErrorWithMetric", TestVerifyOrReturnErrorWithMetric), // - NL_TEST_DEF("VerifyOrReturnValueWithMetric", TestVerifyOrReturnValueWithMetric), // - NL_TEST_DEF("VerifyOrReturnLogErrorWithMetric", TestVerifyOrReturnLogErrorWithMetric), // - NL_TEST_DEF("ReturnErrorCodeWithMetricIf", TestReturnErrorCodeWithMetricIf), // - NL_TEST_DEF("ExitNowWithMetric", TestExitNowWithMetric), // - NL_TEST_DEF("LogErrorOnFailureWithMetric", TestLogErrorOnFailureWithMetric), // - NL_TEST_DEF("VerifyOrDoWithMetric", TestVerifyOrDoWithMetric), // - NL_TEST_SENTINEL() // -}; - } // namespace - -int TestMetricEvents() -{ - nlTestSuite theSuite = { "Metric event tests", &sMetricTests[0], nullptr, nullptr }; - - // Run test suite against one context. - nlTestRunner(&theSuite, nullptr); - return nlTestRunnerStats(&theSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestMetricEvents) diff --git a/src/tracing/tests/TestTracing.cpp b/src/tracing/tests/TestTracing.cpp index 61cf07dc838ce2..88d2a10c772579 100644 --- a/src/tracing/tests/TestTracing.cpp +++ b/src/tracing/tests/TestTracing.cpp @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #include #include - -#include +#include #include #include @@ -52,7 +52,7 @@ class LoggingTraceBackend : public Backend std::vector mTraces; }; -void TestBasicTracing(nlTestSuite * inSuite, void * inContext) +TEST(TestTracing, TestBasicTracing) { LoggingTraceBackend backend; @@ -80,11 +80,11 @@ void TestBasicTracing(nlTestSuite * inSuite, void * inContext) "END:Group:C", "END:Group:B", "BEGIN:Group:E", "END:Group:E", "END:Group:A", }; - NL_TEST_ASSERT(inSuite, backend.traces().size() == expected.size()); - NL_TEST_ASSERT(inSuite, std::equal(backend.traces().begin(), backend.traces().end(), expected.begin(), expected.end())); + EXPECT_EQ(backend.traces().size(), expected.size()); + EXPECT_TRUE(std::equal(backend.traces().begin(), backend.traces().end(), expected.begin(), expected.end())); } -void TestMultipleBackends(nlTestSuite * inSuite, void * inContext) +TEST(TestTracing, TestMultipleBackends) { LoggingTraceBackend b1; LoggingTraceBackend b2; @@ -112,40 +112,23 @@ void TestMultipleBackends(nlTestSuite * inSuite, void * inContext) "BEGIN:G:1", "BEGIN:G:2", "BEGIN:G:3", "END:G:3", "BEGIN:G:4", "END:G:4", "END:G:2", "END:G:1", }; - NL_TEST_ASSERT(inSuite, b1.traces().size() == expected1.size()); - NL_TEST_ASSERT(inSuite, std::equal(b1.traces().begin(), b1.traces().end(), expected1.begin(), expected1.end())); + EXPECT_EQ(b1.traces().size(), expected1.size()); + EXPECT_TRUE(std::equal(b1.traces().begin(), b1.traces().end(), expected1.begin(), expected1.end())); std::vector expected2 = { "BEGIN:G:2", "BEGIN:G:3", "END:G:3", "BEGIN:G:4", "END:G:4", "END:G:2", }; - NL_TEST_ASSERT(inSuite, b2.traces().size() == expected2.size()); - NL_TEST_ASSERT(inSuite, std::equal(b2.traces().begin(), b2.traces().end(), expected2.begin(), expected2.end())); + EXPECT_EQ(b2.traces().size(), expected2.size()); + EXPECT_TRUE(std::equal(b2.traces().begin(), b2.traces().end(), expected2.begin(), expected2.end())); std::vector expected3 = { "BEGIN:G:3", "END:G:3", }; - NL_TEST_ASSERT(inSuite, b3.traces().size() == expected3.size()); - NL_TEST_ASSERT(inSuite, std::equal(b3.traces().begin(), b3.traces().end(), expected3.begin(), expected3.end())); + EXPECT_EQ(b3.traces().size(), expected3.size()); + EXPECT_TRUE(std::equal(b3.traces().begin(), b3.traces().end(), expected3.begin(), expected3.end())); } -const nlTest sTests[] = { - NL_TEST_DEF("BasicTracing", TestBasicTracing), // - NL_TEST_DEF("BasicMultipleBackends", TestMultipleBackends), // - NL_TEST_SENTINEL() // -}; - } // namespace - -int TestTracing() -{ - nlTestSuite theSuite = { "Tracing tests", &sTests[0], nullptr, nullptr }; - - // Run test suite against one context. - nlTestRunner(&theSuite, nullptr); - return nlTestRunnerStats(&theSuite); -} - -CHIP_REGISTER_TEST_SUITE(TestTracing) From 8122739289cf85a50fe63b5b66635bd9d407b141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Fri, 10 May 2024 18:40:05 +0200 Subject: [PATCH 35/39] [crypto] Log PSA crypto error codes in more places (#33403) Log PSA crypto error codes in more places to make it easier to catch and analyze crypto misconfiguration, such as too low number of available key slots. Signed-off-by: Damian Krolik --- src/crypto/CHIPCryptoPALPSA.cpp | 35 +++++++++++++++------------ src/crypto/CHIPCryptoPALPSA.h | 5 ++++ src/crypto/PSAOperationalKeystore.cpp | 1 + src/crypto/PSASessionKeystore.cpp | 5 ++-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/crypto/CHIPCryptoPALPSA.cpp b/src/crypto/CHIPCryptoPALPSA.cpp index 554feb0d52fee4..6eccb1dde8f1ab 100644 --- a/src/crypto/CHIPCryptoPALPSA.cpp +++ b/src/crypto/CHIPCryptoPALPSA.cpp @@ -48,14 +48,6 @@ namespace Crypto { namespace { -void logPsaError(psa_status_t status) -{ - if (status != 0) - { - ChipLogError(Crypto, "PSA error: %d", static_cast(status)); - } -} - bool isBufferNonEmpty(const uint8_t * data, size_t data_length) { return data != nullptr && data_length > 0; @@ -281,6 +273,7 @@ CHIP_ERROR PsaKdf::Init(const ByteSpan & secret, const ByteSpan & salt, const By psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_DERIVE); status = psa_import_key(&attrs, secret.data(), secret.size(), &mSecretKeyId); + LogPsaError(status); psa_reset_key_attributes(&attrs); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); @@ -312,9 +305,18 @@ CHIP_ERROR PsaKdf::InitOperation(psa_key_id_t hkdfKey, const ByteSpan & salt, co return CHIP_NO_ERROR; } +void LogPsaError(psa_status_t status) +{ + if (status != PSA_SUCCESS) + { + ChipLogError(Crypto, "PSA error: %d", static_cast(status)); + } +} + CHIP_ERROR PsaKdf::DeriveBytes(const MutableByteSpan & output) { psa_status_t status = psa_key_derivation_output_bytes(&mOperation, output.data(), output.size()); + LogPsaError(status); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; @@ -323,6 +325,7 @@ CHIP_ERROR PsaKdf::DeriveBytes(const MutableByteSpan & output) CHIP_ERROR PsaKdf::DeriveKey(const psa_key_attributes_t & attributes, psa_key_id_t & keyId) { psa_status_t status = psa_key_derivation_output_key(&attributes, &mOperation, &keyId); + LogPsaError(status); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; @@ -367,6 +370,7 @@ CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const u VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); exit: + LogPsaError(status); psa_destroy_key(keyId); psa_reset_key_attributes(&attrs); @@ -476,6 +480,7 @@ CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * pass, size_t pass_length } exit: + LogPsaError(status); psa_destroy_key(keyId); psa_reset_key_attributes(&attrs); @@ -519,7 +524,7 @@ CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_len error = out_signature.SetLength(outputLen); exit: - logPsaError(status); + LogPsaError(status); return error; } @@ -544,7 +549,7 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, cons VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); exit: - logPsaError(status); + LogPsaError(status); psa_destroy_key(keyId); psa_reset_key_attributes(&attributes); @@ -573,7 +578,7 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, co VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); exit: - logPsaError(status); + LogPsaError(status); psa_destroy_key(keyId); psa_reset_key_attributes(&attributes); @@ -596,7 +601,7 @@ CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_k SuccessOrExit(error = out_secret.SetLength(outputLength)); exit: - logPsaError(status); + LogPsaError(status); return error; } @@ -671,7 +676,7 @@ CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) mInitialized = true; exit: - logPsaError(status); + LogPsaError(status); psa_reset_key_attributes(&attributes); return error; @@ -697,7 +702,7 @@ CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const error = output.SetLength(bbuf.Needed()); exit: - logPsaError(status); + LogPsaError(status); return error; } @@ -728,7 +733,7 @@ CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input) mInitialized = true; exit: - logPsaError(status); + LogPsaError(status); return error; } diff --git a/src/crypto/CHIPCryptoPALPSA.h b/src/crypto/CHIPCryptoPALPSA.h index 2f91b3b4d49765..8fa3dc57a54024 100644 --- a/src/crypto/CHIPCryptoPALPSA.h +++ b/src/crypto/CHIPCryptoPALPSA.h @@ -150,5 +150,10 @@ class PsaKdf psa_key_derivation_operation_t mOperation = PSA_KEY_DERIVATION_OPERATION_INIT; }; +/** + * @brief Log PSA status code if it indicates an error. + */ +void LogPsaError(psa_status_t status); + } // namespace Crypto } // namespace chip diff --git a/src/crypto/PSAOperationalKeystore.cpp b/src/crypto/PSAOperationalKeystore.cpp index b6ba44e0aa2995..09e00bc9b581f9 100644 --- a/src/crypto/PSAOperationalKeystore.cpp +++ b/src/crypto/PSAOperationalKeystore.cpp @@ -160,6 +160,7 @@ CHIP_ERROR PSAOperationalKeystore::PersistentP256Keypair::Deserialize(P256Serial memcpy(mPublicKey.Bytes(), input.ConstBytes(), mPublicKey.Length()); exit: + LogPsaError(status); psa_reset_key_attributes(&attributes); return error; diff --git a/src/crypto/PSASessionKeystore.cpp b/src/crypto/PSASessionKeystore.cpp index 0ae3ed50755495..304fa10086daba 100644 --- a/src/crypto/PSASessionKeystore.cpp +++ b/src/crypto/PSASessionKeystore.cpp @@ -92,6 +92,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke AesKeyAttributes attrs; psa_status_t status = psa_import_key(&attrs.Get(), keyMaterial, sizeof(Symmetric128BitsKeyByteArray), &key.AsMutable()); + LogPsaError(status); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; @@ -105,7 +106,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const Symmetric128BitsKeyByteArray & ke HmacKeyAttributes attrs; psa_status_t status = psa_import_key(&attrs.Get(), keyMaterial, sizeof(Symmetric128BitsKeyByteArray), &key.AsMutable()); - + LogPsaError(status); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; @@ -118,7 +119,7 @@ CHIP_ERROR PSASessionKeystore::CreateKey(const ByteSpan & keyMaterial, HkdfKeyHa HkdfKeyAttributes attrs; psa_status_t status = psa_import_key(&attrs.Get(), keyMaterial.data(), keyMaterial.size(), &key.AsMutable()); - + LogPsaError(status); VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; From 93aa97dbf97f2b8f81b04c1d9ed244cfe3bdc391 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Sat, 11 May 2024 03:17:14 +0900 Subject: [PATCH 36/39] [Android] Implement qr code generator (#33381) * Implement QR Code Parser * Fix QR Code scan, static code * Kotlin codestyle * restore soft_ap feature --- .../google/chip/chiptool/CHIPToolActivity.kt | 2 +- .../chip/chiptool/SelectActionFragment.kt | 7 +- .../CHIPDeviceDetailsFragment.kt | 97 ++++++++++-- .../setuppayloadscanner/CHIPDeviceInfo.kt | 33 ++++- .../res/layout/chip_device_info_fragment.xml | 139 ++++++++++++++---- .../app/src/main/res/values/strings.xml | 6 +- .../onboardingpayload/DiscoveryCapability.kt | 8 +- .../onboardingpayload/OnboardingPayload.kt | 37 ++--- 8 files changed, 256 insertions(+), 73 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt index 7aaaa8d6724756..f5a451f240f0e3 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/CHIPToolActivity.kt @@ -122,7 +122,7 @@ class CHIPToolActivity : startActivity(redirectIntent) } - override fun SetNetworkType(type: ProvisionNetworkType) { + override fun setNetworkType(type: ProvisionNetworkType?) { networkType = type } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index f935ab37926927..69bfdc109912c9 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -154,7 +154,7 @@ class SelectActionFragment : Fragment() { /** Notifies listener of a click to manually input the CHIP device address. */ fun onShowDeviceAddressInput() - fun SetNetworkType(type: ProvisionNetworkType) + fun setNetworkType(type: ProvisionNetworkType?) } private fun showFragment(fragment: Fragment, showOnBack: Boolean = true) { @@ -172,6 +172,7 @@ class SelectActionFragment : Fragment() { /** Notifies listener of Scan QR code button click. */ private fun handleScanQrCodeClicked() { + getCallback()?.setNetworkType(null) showFragment(BarcodeFragment.newInstance()) } @@ -226,13 +227,13 @@ class SelectActionFragment : Fragment() { /** Notifies listener of provision-WiFi-credentials button click. */ private fun handleProvisionWiFiCredentialsClicked() { - getCallback()?.SetNetworkType(ProvisionNetworkType.WIFI) + getCallback()?.setNetworkType(ProvisionNetworkType.WIFI) showFragment(BarcodeFragment.newInstance()) } /** Notifies listener of provision-Thread-credentials button click. */ private fun handleProvisionThreadCredentialsClicked() { - getCallback()?.SetNetworkType(ProvisionNetworkType.THREAD) + getCallback()?.setNetworkType(ProvisionNetworkType.THREAD) showFragment(BarcodeFragment.newInstance()) } diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt index b2b27ee31da900..ea131c0e726bcb 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceDetailsFragment.kt @@ -18,7 +18,12 @@ package com.google.chip.chiptool.setuppayloadscanner +import android.content.Intent +import android.net.Uri import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -27,6 +32,10 @@ import androidx.fragment.app.Fragment import com.google.chip.chiptool.R import com.google.chip.chiptool.databinding.ChipDeviceInfoFragmentBinding import com.google.chip.chiptool.util.FragmentUtil +import java.net.URLEncoder +import matter.onboardingpayload.OnboardingPayload +import matter.onboardingpayload.OnboardingPayloadException +import matter.onboardingpayload.QRCodeOnboardingPayloadGenerator /** Show the [CHIPDeviceInfo]. */ class CHIPDeviceDetailsFragment : Fragment() { @@ -35,6 +44,8 @@ class CHIPDeviceDetailsFragment : Fragment() { private val binding get() = _binding!! + private lateinit var onBoardingPayload: OnboardingPayload + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -43,17 +54,13 @@ class CHIPDeviceDetailsFragment : Fragment() { _binding = ChipDeviceInfoFragmentBinding.inflate(inflater, container, false) deviceInfo = checkNotNull(requireArguments().getParcelable(ARG_DEVICE_INFO)) - binding.versionTv.text = "${deviceInfo.version}" - binding.vendorIdTv.text = "${deviceInfo.vendorId}" - binding.productIdTv.text = "${deviceInfo.productId}" - binding.setupCodeTv.text = "${deviceInfo.setupPinCode}" - binding.discriminatorTv.text = "${deviceInfo.discriminator}" - binding.discoveryCapabilitiesTv.text = - requireContext() - .getString( - R.string.chip_device_info_discovery_capabilities_text, - deviceInfo.discoveryCapabilities - ) + binding.versionEd.setText(deviceInfo.version.toString()) + binding.vendorIdEd.setText(deviceInfo.vendorId.toString()) + binding.productIdEd.setText(deviceInfo.productId.toString()) + binding.setupCodeEd.setText(deviceInfo.setupPinCode.toString()) + binding.discriminatorEd.setText(deviceInfo.discriminator.toString()) + binding.serialNumberEd.setText(deviceInfo.serialNumber) + binding.discoveryCapabilitiesTv.text = "${deviceInfo.discoveryCapabilities}" if (deviceInfo.optionalQrCodeInfoMap.isEmpty()) { binding.vendorTagsLabelTv.visibility = View.GONE @@ -70,7 +77,7 @@ class CHIPDeviceDetailsFragment : Fragment() { } } - binding.commissioningFlowTv.text = "${deviceInfo.commissioningFlow}" + binding.commissioningFlowEd.setText(deviceInfo.commissioningFlow.toString()) // commissioningFlow = 2 (Custom), read device info from Ledger if (deviceInfo.commissioningFlow == 2) { @@ -81,9 +88,74 @@ class CHIPDeviceDetailsFragment : Fragment() { } } + onBoardingPayload = deviceInfo.toSetupPayload() + binding.qrCodeTv.text = + QRCodeOnboardingPayloadGenerator(onBoardingPayload) + .payloadBase38RepresentationWithAutoTLVBuffer() + + setDiscoveryCapabilitiesEditTextListener() + setQRCodeButtonListener() + return binding.root } + private fun setDiscoveryCapabilitiesEditTextListener() { + binding.discoveryCapabilitiesEd.setText(onBoardingPayload.getRendezvousInformation().toString()) + binding.discoveryCapabilitiesEd.addTextChangedListener( + object : TextWatcher { + override fun onTextChanged(value: CharSequence?, p1: Int, p2: Int, p3: Int) { + if (value.isNullOrEmpty()) { + return + } + onBoardingPayload.setRendezvousInformation(value.toString().toLong()) + binding.discoveryCapabilitiesTv.text = "${onBoardingPayload.discoveryCapabilities}" + } + + override fun afterTextChanged(p0: Editable?) { + // no_op + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + // no_op + } + } + ) + } + + private fun setQRCodeButtonListener() { + binding.showQRCodeBtn.setOnClickListener { + onBoardingPayload.apply { + version = binding.versionEd.text.toString().toInt() + vendorId = binding.vendorIdEd.text.toString().toInt() + productId = binding.productIdEd.text.toString().toInt() + commissioningFlow = binding.commissioningFlowEd.text.toString().toInt() + setupPinCode = binding.setupCodeEd.text.toString().toLong() + discriminator = binding.discriminatorEd.text.toString().toInt() + val serialNumber = binding.serialNumberEd.text.toString() + try { + removeSerialNumber() + } catch (e: OnboardingPayloadException) { + Log.d(TAG, "Serial Number not set!", e) + } + if (serialNumber.isNotEmpty()) { + addSerialNumber(binding.serialNumberEd.text.toString()) + } + } + val qrCode = + QRCodeOnboardingPayloadGenerator(onBoardingPayload) + .payloadBase38RepresentationWithAutoTLVBuffer() + Log.d(TAG, "QR Code : $qrCode") + binding.qrCodeTv.text = qrCode + } + + binding.showQRCodeUriBtn.setOnClickListener { + val qrCodeEncode = URLEncoder.encode(binding.qrCodeTv.text.toString(), "UTF-8") + val qrCodeUri = getString(R.string.chip_device_info_qrcode_uri, qrCodeEncode) + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(qrCodeUri)) + startActivity(intent) + } + } + override fun onDestroyView() { super.onDestroyView() _binding = null @@ -96,6 +168,7 @@ class CHIPDeviceDetailsFragment : Fragment() { } companion object { + private const val TAG = "CHIPDeviceDetailsFragment" private const val ARG_DEVICE_INFO = "device_info" @JvmStatic diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt index d8fb51bbb3d844..28cfaa11f162c6 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/setuppayloadscanner/CHIPDeviceInfo.kt @@ -19,9 +19,11 @@ package com.google.chip.chiptool.setuppayloadscanner import android.os.Parcelable +import android.util.Log import kotlinx.parcelize.Parcelize import matter.onboardingpayload.DiscoveryCapability import matter.onboardingpayload.OnboardingPayload +import matter.onboardingpayload.OnboardingPayloadException /** Class to hold the CHIP device information. */ @Parcelize @@ -35,12 +37,40 @@ data class CHIPDeviceInfo( val optionalQrCodeInfoMap: Map = mapOf(), val discoveryCapabilities: MutableSet = mutableSetOf(), val isShortDiscriminator: Boolean = false, + val serialNumber: String = "", val ipAddress: String? = null, val port: Int = 5540 ) : Parcelable { + fun toSetupPayload(): OnboardingPayload { + val onboardingPayload = + OnboardingPayload( + version, + vendorId, + productId, + commissioningFlow, + discoveryCapabilities, + discriminator, + isShortDiscriminator, + setupPinCode + ) + if (serialNumber.isNotEmpty()) { + onboardingPayload.addSerialNumber(serialNumber) + } + return onboardingPayload + } + companion object { + private const val TAG = "CHIPDeviceInfo" + fun fromSetupPayload(setupPayload: OnboardingPayload): CHIPDeviceInfo { + val serialNumber = + try { + setupPayload.getSerialNumber() + } catch (e: OnboardingPayloadException) { + Log.d(TAG, "serialNumber Exception", e) + "" + } return CHIPDeviceInfo( setupPayload.version, setupPayload.vendorId, @@ -52,7 +82,8 @@ data class CHIPDeviceInfo( QrCodeInfo(info.tag, info.type, info.data, info.int32) }, setupPayload.discoveryCapabilities, - setupPayload.hasShortDiscriminator + setupPayload.hasShortDiscriminator, + serialNumber ) } } diff --git a/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml index 6e326a65008edb..4997681993ca29 100644 --- a/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml +++ b/examples/android/CHIPTool/app/src/main/res/layout/chip_device_info_fragment.xml @@ -1,5 +1,6 @@ @@ -26,16 +27,18 @@ android:layout_below="@id/titleTv" android:layout_alignParentStart="true" android:textSize="20sp"/> - + android:textSize="11sp" + android:autofillHints="@string/chip_device_info_version_label" + android:inputType="number" + tools:ignore="LabelFor" /> - + android:textSize="11sp" + android:autofillHints="@string/chip_device_info_vendor_id_label" + android:inputType="number" + tools:ignore="LabelFor" /> - + android:textSize="11sp" + android:autofillHints="@string/chip_device_info_product_id_label" + android:inputType="number" + tools:ignore="LabelFor" /> - + android:textSize="11sp" + android:autofillHints="@string/chip_device_info_discriminator_label" + android:inputType="number" + tools:ignore="LabelFor" /> - + android:textSize="11sp" + android:autofillHints="@string/chip_device_info_setup_code_label" + android:inputType="number" + tools:ignore="LabelFor" /> + + @@ -152,27 +184,82 @@ android:layout_below="@id/discoveryCapabilitiesTv" android:layout_alignParentStart="true" android:textSize="20sp"/> - + + +