3 * Copyright (c) 2020-2021 Project CHIP Authors
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file defines objects for a CHIP Interaction Data model Engine which handle unsolicitied IM message, and
22 * manage different kinds of IM client and handlers.
26 #include "InteractionModelEngine.h"
28 #include "CommandHandler.h"
29 #include "CommandSender.h"
34 InteractionModelEngine sInteractionModelEngine;
36 InteractionModelEngine::InteractionModelEngine() {}
38 InteractionModelEngine * InteractionModelEngine::GetInstance()
40 return &sInteractionModelEngine;
43 CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate)
45 CHIP_ERROR err = CHIP_NO_ERROR;
47 mpExchangeMgr = apExchangeMgr;
48 mpDelegate = apDelegate;
50 err = mpExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id, this);
57 void InteractionModelEngine::Shutdown()
59 for (auto & commandSender : mCommandSenderObjs)
61 commandSender.Shutdown();
64 for (auto & commandHandler : mCommandHandlerObjs)
66 commandHandler.Shutdown();
69 for (auto & readClient : mReadClients)
71 readClient.Shutdown();
74 for (auto & readHandler : mReadHandlers)
76 readHandler.Shutdown();
80 CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apCommandSender)
82 CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
83 *apCommandSender = nullptr;
85 for (auto & commandSender : mCommandSenderObjs)
87 if (commandSender.IsFree())
89 *apCommandSender = &commandSender;
90 err = commandSender.Init(mpExchangeMgr, mpDelegate);
91 if (CHIP_NO_ERROR != err)
93 *apCommandSender = nullptr;
104 CHIP_ERROR InteractionModelEngine::NewReadClient(ReadClient ** const apReadClient)
106 CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
108 for (auto & readClient : mReadClients)
110 if (readClient.IsFree())
112 *apReadClient = &readClient;
113 err = readClient.Init(mpExchangeMgr, mpDelegate);
114 if (CHIP_NO_ERROR != err)
116 *apReadClient = nullptr;
125 void InteractionModelEngine::OnUnknownMsgType(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
126 const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
128 CHIP_ERROR err = CHIP_NO_ERROR;
130 ChipLogDetail(DataManagement, "Msg type %d not supported", aPayloadHeader.GetMessageType());
132 // Todo: Add status report
133 // err = SendStatusReport(ec, kChipProfile_Common, kStatus_UnsupportedMessage);
134 // SuccessOrExit(err);
136 apExchangeContext->Close();
137 apExchangeContext = nullptr;
139 ChipLogFunctError(err);
141 // Todo: Fix the below check after the above status report is implemented.
142 if (nullptr != apExchangeContext)
144 apExchangeContext->Abort();
148 void InteractionModelEngine::OnInvokeCommandRequest(Messaging::ExchangeContext * apExchangeContext,
149 const PacketHeader & aPacketHeader, const PayloadHeader & aPayloadHeader,
150 System::PacketBufferHandle aPayload)
152 CHIP_ERROR err = CHIP_NO_ERROR;
154 for (auto & commandHandler : mCommandHandlerObjs)
156 if (commandHandler.IsFree())
158 err = commandHandler.Init(mpExchangeMgr, mpDelegate);
160 commandHandler.OnMessageReceived(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
161 apExchangeContext = nullptr;
167 ChipLogFunctError(err);
169 if (nullptr != apExchangeContext)
171 apExchangeContext->Abort();
175 void InteractionModelEngine::OnReadRequest(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
176 const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
178 CHIP_ERROR err = CHIP_NO_ERROR;
180 ChipLogDetail(DataManagement, "Receive Read request");
182 for (auto & readHandler : mReadHandlers)
184 if (readHandler.IsFree())
186 err = readHandler.Init(mpDelegate);
188 err = readHandler.OnReadRequest(apExchangeContext, std::move(aPayload));
190 apExchangeContext = nullptr;
196 ChipLogFunctError(err);
198 if (nullptr != apExchangeContext)
200 apExchangeContext->Abort();
204 void InteractionModelEngine::OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
205 const PayloadHeader & aPayloadHeader, System::PacketBufferHandle aPayload)
207 if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::InvokeCommandRequest))
210 OnInvokeCommandRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
212 else if (aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::ReadRequest))
214 OnReadRequest(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
218 OnUnknownMsgType(apExchangeContext, aPacketHeader, aPayloadHeader, std::move(aPayload));
222 void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec)
224 ChipLogProgress(DataManagement, "Time out! failed to receive echo response from Exchange: %d", ec->GetExchangeId());
227 // The default implementation to make compiler happy before codegen for this is ready.
228 // TODO: Remove this after codegen is ready.
229 void __attribute__((weak))
230 DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
231 chip::TLV::TLVReader & aReader, Command * apCommandObj)
233 ChipLogDetail(DataManagement, "Received Cluster Command: Cluster=%" PRIx16 " Command=%" PRIx8 " Endpoint=%" PRIx8, aClusterId,
234 aCommandId, aEndPointId);
237 "Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands");
240 uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * const apReadClient) const
242 return static_cast<uint16_t>(apReadClient - mReadClients);