| /* | |
| * | |
| * Copyright (c) 2026 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 <app/CommandHandler.h> | |
| #include <app/ConcreteCommandPath.h> | |
| #include <lib/core/ScopedNodeId.h> | |
| namespace chip { | |
| namespace app { | |
| namespace Clusters { | |
| namespace AvAnalysis { | |
| /** | |
| * A camera-bound command (EstablishAnalysisStream, RemoveAnalysisStream, ActivateAnalysisStream, | |
| * DeactivateAnalysisStream) cannot be answered until the camera responds, so its CommandHandler is | |
| * parked here and the interaction advances through this state machine | |
| * Exactly one interaction exists at a time; a command arriving while InFlight() is answered Busy. | |
| */ | |
| class CameraInteraction | |
| { | |
| public: | |
| enum class State : uint8_t | |
| { | |
| kIdle, // No camera interaction in flight | |
| kEstablishing, // VideoStreamAllocate awaiting the camera's answer | |
| kRemoving, // VideoStreamDeallocate awaiting the camera's answer | |
| kActivating, // WebRTC session initiation awaiting the offer exchange's outcome | |
| kDeactivating, // WebRTC EndSession awaiting the camera's answer | |
| }; | |
| State GetState() const { return mState; } | |
| bool InFlight() const { return mState != State::kIdle; } | |
| /** | |
| * The camera the in-flight interaction is bound to. | |
| */ | |
| const ScopedNodeId & CameraNode() const { return mCameraNode; } | |
| /** | |
| * The AnalysisStreamID the in-flight interaction is about | |
| */ | |
| uint16_t AnalysisStreamId() const { return mAnalysisStreamId; } | |
| /** | |
| * The camera endpoint having WebRTCTransportProvider | |
| */ | |
| EndpointId WebRTCEndpoint() const { return mWebRTCEndpoint; } | |
| /** | |
| * Enters aState, parking the command so it can be answered when the camera responds. | |
| */ | |
| void Begin(State aState, CommandHandler & aHandler, const ConcreteCommandPath & aPath, const ScopedNodeId & aCameraNode, | |
| uint16_t aAnalysisStreamId = 0, EndpointId aWebRTCEndpoint = kInvalidEndpointId) | |
| { | |
| mState = aState; | |
| mHandle = CommandHandler::Handle(&aHandler); | |
| mPath = aPath; | |
| mCameraNode = aCameraNode; | |
| mAnalysisStreamId = aAnalysisStreamId; | |
| mWebRTCEndpoint = aWebRTCEndpoint; | |
| aHandler.FlushAcksRightAwayOnSlowCommand(); | |
| } | |
| /** | |
| * Rolls back a Begin whose camera request could not be started | |
| */ | |
| void Abort() | |
| { | |
| mState = State::kIdle; | |
| mHandle = CommandHandler::Handle(); | |
| ClearInteractionState(); | |
| } | |
| /** | |
| * Ends the interaction: returns the parked handle. The camera node and stream id are cleared, | |
| * so callers needing them must read them before completing. | |
| */ | |
| CommandHandler::Handle Complete(ConcreteCommandPath & outPath) | |
| { | |
| outPath = mPath; | |
| mState = State::kIdle; | |
| ClearInteractionState(); | |
| return std::move(mHandle); | |
| } | |
| private: | |
| void ClearInteractionState() | |
| { | |
| mAnalysisStreamId = 0; | |
| mWebRTCEndpoint = kInvalidEndpointId; | |
| mCameraNode = ScopedNodeId(); | |
| mPath = ConcreteCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); | |
| } | |
| State mState = State::kIdle; | |
| uint16_t mAnalysisStreamId = 0; | |
| EndpointId mWebRTCEndpoint = kInvalidEndpointId; | |
| CommandHandler::Handle mHandle; | |
| ConcreteCommandPath mPath = ConcreteCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); | |
| ScopedNodeId mCameraNode; | |
| }; | |
| } // namespace AvAnalysis | |
| } // namespace Clusters | |
| } // namespace app | |
| } // namespace chip |