diff --git a/examples/lock-app/linux/src/LockAppCommandDelegate.cpp b/examples/lock-app/linux/src/LockAppCommandDelegate.cpp index 92602a70c022c2..563de47afa4667 100644 --- a/examples/lock-app/linux/src/LockAppCommandDelegate.cpp +++ b/examples/lock-app/linux/src/LockAppCommandDelegate.cpp @@ -17,6 +17,7 @@ */ #include "LockAppCommandDelegate.h" +#include #include #include @@ -36,6 +37,10 @@ class LockAppCommandHandler {} private: + // aCommand should be "lock" or "unlock". + static CHIP_ERROR ExtractPINFromParams(const char * aCommand, const Json::Value & aParams, Optional & aPIN, + chip::Platform::ScopedMemoryBuffer & aPINBuffer); + std::string mCommandName; Json::Value mCommandParameters; }; @@ -131,6 +136,39 @@ void LockAppCommandHandler::HandleCommand(intptr_t context) alarmCode)); LockManager::Instance().SendLockAlarm(endpointId, static_cast(alarmCode)); } + else if (self->mCommandName == "Lock") + { + + VerifyOrExit(params["OperationSource"].isUInt(), + ChipLogError(NotSpecified, "Lock App: Unable to execute command to lock: invalid type for OperationSource")); + + auto operationSource = params["OperationSource"].asUInt(); + + Optional pin; + chip::Platform::ScopedMemoryBuffer pinBuffer; + SuccessOrExit(ExtractPINFromParams("lock", params, pin, pinBuffer)); + + OperationErrorEnum error = OperationErrorEnum::kUnspecified; + LockManager::Instance().Lock(endpointId, NullNullable, NullNullable, pin, error, OperationSourceEnum(operationSource)); + VerifyOrExit(error == OperationErrorEnum::kUnspecified, + ChipLogError(NotSpecified, "Lock App: Lock error received: %u", to_underlying(error))); + } + else if (self->mCommandName == "Unlock") + { + VerifyOrExit(params["OperationSource"].isUInt(), + ChipLogError(NotSpecified, "Lock App: Unable to execute command to unlock: invalid type for OperationSource")); + + auto operationSource = params["OperationSource"].asUInt(); + + Optional pin; + chip::Platform::ScopedMemoryBuffer pinBuffer; + SuccessOrExit(ExtractPINFromParams("unlock", params, pin, pinBuffer)); + + OperationErrorEnum error = OperationErrorEnum::kUnspecified; + LockManager::Instance().Unlock(endpointId, NullNullable, NullNullable, pin, error, OperationSourceEnum(operationSource)); + VerifyOrExit(error == OperationErrorEnum::kUnspecified, + ChipLogError(NotSpecified, "Lock App: Unlock error received: %u", to_underlying(error))); + } else { ChipLogError(NotSpecified, "Lock App: Unable to execute command \"%s\": command not supported", self->mCommandName.c_str()); @@ -140,6 +178,56 @@ void LockAppCommandHandler::HandleCommand(intptr_t context) chip::Platform::Delete(self); } +CHIP_ERROR LockAppCommandHandler::ExtractPINFromParams(const char * aCommand, const Json::Value & aParams, + Optional & aPIN, + chip::Platform::ScopedMemoryBuffer & aPINBuffer) +{ + if (aParams.isMember("PINAsHex")) + { + // Hex-encoded PIN bytes. So a PIN consisting of the numbers 123 gets encoded as the string "313233" + VerifyOrReturnError( + aParams["PINAsHex"].isString(), CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(NotSpecified, "Lock App: Unable to execute command to %s: invalid type for PIN", aCommand)); + + auto pinAsHex = aParams["PINAsHex"].asString(); + size_t size = pinAsHex.length(); + VerifyOrReturnError(size % 2 == 0, CHIP_ERROR_INVALID_STRING_LENGTH); + + size_t bufferSize = size / 2; + + VerifyOrReturnError(aPINBuffer.Calloc(bufferSize), CHIP_ERROR_NO_MEMORY); + size_t octetCount = chip::Encoding::HexToBytes(pinAsHex.c_str(), size, aPINBuffer.Get(), bufferSize); + VerifyOrReturnError( + octetCount != 0 || size == 0, CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(NotSpecified, "Lock app: Unable to execute command to %s: invalid hex value for PIN", aCommand)); + + aPIN.Emplace(aPINBuffer.Get(), octetCount); + ChipLogProgress(NotSpecified, "Lock App: Received command to %s with hex PIN: %s", aCommand, pinAsHex.c_str()); + } + else if (aParams.isMember("PINAsString")) + { + // ASCII-encoded PIN bytes. So a PIN consisting of the numbers 123 gets encoded as the string "123" + VerifyOrReturnError( + aParams["PINAsString"].isString(), CHIP_ERROR_INVALID_ARGUMENT, + ChipLogError(NotSpecified, "Lock App: Unable to execute command to %s: invalid type for PIN", aCommand)); + + auto pinAsString = aParams["PINAsString"].asString(); + size_t bufferSize = pinAsString.length(); + + VerifyOrReturnError(aPINBuffer.Calloc(bufferSize), CHIP_ERROR_NO_MEMORY); + memcpy(aPINBuffer.Get(), pinAsString.c_str(), bufferSize); + aPIN.Emplace(aPINBuffer.Get(), bufferSize); + + ChipLogProgress(NotSpecified, "Lock App: Received command to %s with string PIN: %s", aCommand, pinAsString.c_str()); + } + else + { + aPIN.ClearValue(); + } + + return CHIP_NO_ERROR; +} + void LockAppCommandDelegate::OnEventCommandReceived(const char * json) { auto handler = LockAppCommandHandler::FromJSON(json);