blob: 0bddea4f17a73a9751016af1b87de19f3e4382ce [file] [log] [blame]
/*
*
* Copyright (c) 2025 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 "OtaProviderAppCommandDelegate.h"
#include <lib/support/Defer.h>
#include <platform/PlatformManager.h>
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::DeviceLayer;
OtaProviderAppCommandHandler * OtaProviderAppCommandHandler::FromJSON(const char * json, OtaProviderAppCommandDelegate * delegate)
{
Json::Reader reader;
Json::Value value;
if (!reader.parse(json, value))
{
ChipLogError(NotSpecified,
"OTA Provider Example: Error parsing JSON with error %s:", reader.getFormattedErrorMessages().c_str());
return nullptr;
}
if (value.empty() || !value.isObject())
{
ChipLogError(NotSpecified, "OTA Provider Example: Invalid JSON command received");
return nullptr;
}
if (!value.isMember("Name") || !value["Name"].isString())
{
ChipLogError(NotSpecified, "OTA Provider Example: Invalid JSON command received: command name is missing");
return nullptr;
}
return Platform::New<OtaProviderAppCommandHandler>(OtaProviderAppCommandHandler::PrivateCtorTag{}, std::move(value), delegate);
}
static std::string ToString(const Json::Value & v)
{
Json::StreamWriterBuilder w;
w["indentation"] = "";
return Json::writeString(w, v);
}
Json::Value OtaProviderAppCommandHandler::BuildOtaProviderSnapshot(uint16_t endpoint)
{
Json::Value payload(Json::objectValue);
payload["VendorID"] = GetOtaProviderExample().GetVendorId();
payload["ProductID"] = GetOtaProviderExample().GetProductId();
payload["SoftwareVersion"] = GetOtaProviderExample().GetSoftwareVersion();
payload["HardwareVersion"] = GetOtaProviderExample().GetHardwareVersion();
payload["Location"] = GetOtaProviderExample().GetLocation();
payload["RequestorCanConsent"] = GetOtaProviderExample().GetRequestorCanConsent();
const auto & protos = GetOtaProviderExample().GetProtocolsSupported();
Json::Value arr(Json::arrayValue);
for (size_t i = 0; i < GetOtaProviderExample().kProtocolsSupportedCount; ++i)
{
arr.append(Json::UInt(protos[i]));
}
payload["ProtocolsSupported"] = arr;
return payload;
}
void OtaProviderAppCommandHandler::HandleCommand(intptr_t context)
{
auto * self = reinterpret_cast<OtaProviderAppCommandHandler *>(context);
if (self == nullptr)
{
return;
}
auto cleanup = MakeDefer([&]() { Platform::Delete(self); });
std::string name;
std::string cluster;
uint16_t endpoint = 0;
OtaProviderAppCommandDelegate * delegate = nullptr;
if (self->mCommandPayload.empty())
{
ChipLogError(NotSpecified, "Invalid JSON event command received");
return;
}
name = self->mCommandPayload["Name"].asString();
cluster = self->mCommandPayload.get("Cluster", "").asString();
endpoint = static_cast<uint16_t>(self->mCommandPayload.get("Endpoint", 0).asUInt());
delegate = self->mDelegate;
if (name == "QueryImageSnapshot")
{
Json::Value out(Json::objectValue);
out["Name"] = "SnapshotResponse";
out["Cluster"] = cluster;
out["Endpoint"] = endpoint;
if (cluster == "OtaSoftwareUpdateProvider")
{
out["Payload"] = self->BuildOtaProviderSnapshot(endpoint);
}
else
{
out["Error"] = "Unsupported cluster for snapshot";
}
if (delegate && delegate->GetPipes())
{
delegate->GetPipes()->WriteToOutPipe(ToString(out));
}
return;
}
ChipLogError(NotSpecified, "Unhandled command: Should never happen");
}
void OtaProviderAppCommandDelegate::OnEventCommandReceived(const char * json)
{
auto handler = OtaProviderAppCommandHandler::FromJSON(json, this);
if (nullptr == handler)
{
ChipLogError(NotSpecified, "OTA Provider App: Unable to instantiate a command handler");
return;
}
// Defer handling to the platform work queue to ensure this command is executed asynchronously and not from the command parsing
// context
SuccessOrDie(PlatformMgr().ScheduleWork(OtaProviderAppCommandHandler::HandleCommand, reinterpret_cast<intptr_t>(handler)));
}