| /* |
| * |
| * Copyright (c) 2021 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. |
| */ |
| |
| /** |
| * @file Contains shell commands for a commissionee (eg. end device) related to commissioning. |
| */ |
| |
| #include <app-common/zap-generated/attribute-id.h> |
| #include <app-common/zap-generated/cluster-id.h> |
| #include <app-common/zap-generated/ids/Attributes.h> |
| #include <app-common/zap-generated/ids/Clusters.h> |
| #include <app/util/ContentAppPlatform.h> |
| #include <cstdio> |
| #include <inttypes.h> |
| #include <lib/core/CHIPCore.h> |
| #include <lib/core/DataModelTypes.h> |
| #include <lib/support/CHIPArgParser.hpp> |
| #include <lib/support/CHIPMem.h> |
| #include <lib/support/CodeUtils.h> |
| #include <lib/support/ZclString.h> |
| #include <platform/CHIPDeviceLayer.h> |
| |
| using namespace chip; |
| using namespace chip::AppPlatform; |
| |
| #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED |
| |
| // Device Version for dynamic endpoints: |
| #define DEVICE_VERSION_DEFAULT 1 |
| |
| EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId, |
| EmberAfAttributeMetadata * attributeMetadata, uint16_t manufacturerCode, |
| uint8_t * buffer, uint16_t maxReadLength) |
| { |
| uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); |
| |
| ChipLogProgress(DeviceLayer, "emberAfExternalAttributeReadCallback endpoint %d ", endpointIndex); |
| |
| EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; |
| |
| ContentApp * app = chip::AppPlatform::AppPlatform::GetInstance().GetContentAppByEndpointId(endpoint); |
| if (app != NULL) |
| { |
| ret = app->HandleReadAttribute(clusterId, attributeMetadata->attributeId, buffer, maxReadLength); |
| } |
| |
| return ret; |
| } |
| |
| EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId, |
| EmberAfAttributeMetadata * attributeMetadata, uint16_t manufacturerCode, |
| uint8_t * buffer) |
| { |
| uint16_t endpointIndex = emberAfGetDynamicIndexFromEndpoint(endpoint); |
| |
| ChipLogProgress(DeviceLayer, "emberAfExternalAttributeWriteCallback endpoint %d ", endpointIndex); |
| |
| EmberAfStatus ret = EMBER_ZCL_STATUS_FAILURE; |
| |
| ContentApp * app = chip::AppPlatform::AppPlatform::GetInstance().GetContentAppByEndpointId(endpoint); |
| if (app != NULL) |
| { |
| ret = app->HandleWriteAttribute(clusterId, attributeMetadata->attributeId, buffer); |
| } |
| |
| return ret; |
| } |
| |
| namespace chip { |
| namespace AppPlatform { |
| |
| int AppPlatform::AddContentApp(ContentApp * app, EmberAfEndpointType * ep, uint16_t deviceType) |
| { |
| ChipLogProgress(DeviceLayer, "Adding device %s ", app->GetApplicationBasic()->GetApplicationName()); |
| uint8_t index = 0; |
| // check if already loaded |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| if (mContentApps[index] == app) |
| { |
| ChipLogProgress(DeviceLayer, "Already added"); |
| return index; |
| } |
| index++; |
| } |
| |
| index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| if (NULL == mContentApps[index]) |
| { |
| mContentApps[index] = app; |
| EmberAfStatus ret; |
| while (1) |
| { |
| ret = emberAfSetDynamicEndpoint(index, mCurrentEndpointId, ep, deviceType, DEVICE_VERSION_DEFAULT); |
| if (ret == EMBER_ZCL_STATUS_SUCCESS) |
| { |
| ChipLogProgress(DeviceLayer, "Added device %s to dynamic endpoint %d (index=%d)", |
| app->GetApplicationBasic()->GetApplicationName(), mCurrentEndpointId, index); |
| app->SetEndpointId(mCurrentEndpointId); |
| return index; |
| } |
| else if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS) |
| { |
| ChipLogProgress(DeviceLayer, "Adding device error=%d", ret); |
| return -1; |
| } |
| // Handle wrap condition |
| if (++mCurrentEndpointId < mFirstDynamicEndpointId) |
| { |
| mCurrentEndpointId = mFirstDynamicEndpointId; |
| } |
| } |
| } |
| index++; |
| } |
| ChipLogProgress(DeviceLayer, "Failed to add dynamic endpoint: No endpoints available!"); |
| return -1; |
| } |
| |
| int AppPlatform::RemoveContentApp(ContentApp * app) |
| { |
| uint8_t index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| if (mContentApps[index] == app) |
| { |
| EndpointId ep = emberAfClearDynamicEndpoint(index); |
| mContentApps[index] = NULL; |
| ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", |
| app->GetApplicationBasic()->GetApplicationName(), ep, index); |
| // Silence complaints about unused ep when progress logging |
| // disabled. |
| UNUSED_VAR(ep); |
| return index; |
| } |
| index++; |
| } |
| return -1; |
| } |
| |
| void AppPlatform::SetupAppPlatform() |
| { |
| ChipLogProgress(DeviceLayer, "AppPlatform::SetupAppPlatform()"); |
| |
| // Clear out the device database |
| uint8_t index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| mContentApps[index] = NULL; |
| index++; |
| } |
| |
| // Set starting endpoint id where dynamic endpoints will be assigned, which |
| // will be the next consecutive endpoint id after the last fixed endpoint. |
| mFirstDynamicEndpointId = static_cast<chip::EndpointId>( |
| static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1))) + 1); |
| mCurrentEndpointId = mFirstDynamicEndpointId; |
| |
| { |
| for (int i = 0; i < emberAfFixedEndpointCount(); i++) |
| { |
| ChipLogProgress(DeviceLayer, "endpoint index=%d, id=%d", i, |
| static_cast<chip::EndpointId>(static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(i))))); |
| } |
| } |
| |
| if (mCurrentEndpointId < emberAfFixedEndpointCount()) |
| { |
| mCurrentEndpointId = emberAfFixedEndpointCount(); |
| } |
| |
| ChipLogProgress(DeviceLayer, "emberAfFixedEndpointCount()=%d mCurrentEndpointId=%d", emberAfFixedEndpointCount(), |
| mCurrentEndpointId); |
| |
| // Disable last fixed endpoint, which is used as a placeholder for all of the |
| // supported clusters so that ZAP will generated the requisite code. |
| // emberAfEndpointEnableDisable(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1)), false); |
| } |
| |
| void AppPlatform::UnloadContentAppByVendorId(uint16_t vendorId) |
| { |
| uint8_t index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| ContentApp * app = mContentApps[index]; |
| if (app != NULL && app->GetApplicationBasic()->GetVendorId() == vendorId) |
| { |
| EndpointId ep = emberAfClearDynamicEndpoint(index); |
| mContentApps[index] = NULL; |
| ChipLogProgress(DeviceLayer, "Removed device %s from dynamic endpoint %d (index=%d)", |
| app->GetApplicationBasic()->GetApplicationName(), ep, index); |
| // Silence complaints about unused ep when progress logging |
| // disabled. |
| UNUSED_VAR(ep); |
| return; |
| } |
| index++; |
| } |
| return; |
| } |
| |
| ContentApp * AppPlatform::GetLoadContentAppByVendorId(uint16_t vendorId) |
| { |
| ChipLogProgress(DeviceLayer, "GetLoadContentAppByVendorId() - vendorId %d ", vendorId); |
| uint8_t index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| ContentApp * app = mContentApps[index]; |
| if (app != NULL && app->GetApplicationBasic()->GetVendorId() == vendorId) |
| { |
| return app; |
| } |
| index++; |
| } |
| if (mContentAppFactory != NULL) |
| { |
| return mContentAppFactory->LoadContentAppByVendorId(vendorId); |
| } |
| return NULL; |
| } |
| |
| ContentApp * AppPlatform::GetLoadContentAppByAppId(Application application) |
| { |
| ChipLogProgress(DeviceLayer, "GetLoadContentAppByAppId()"); |
| if (mContentAppFactory != NULL) |
| { |
| return mContentAppFactory->LoadContentAppByAppId(application); |
| } |
| return NULL; |
| } |
| |
| ContentApp * AppPlatform::GetContentAppByEndpointId(chip::EndpointId id) |
| { |
| uint8_t index = 0; |
| while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) |
| { |
| ContentApp * app = mContentApps[index]; |
| if (app != NULL && app->GetEndpointId() == id) |
| { |
| return app; |
| } |
| index++; |
| } |
| ChipLogProgress(DeviceLayer, "GetContentAppByEndpointId() - endpoint %d not found ", id); |
| return NULL; |
| } |
| |
| } // namespace AppPlatform |
| } // namespace chip |
| |
| #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED |