Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Chef] Add 2 Generic Switch devices and RPC Actions for Testing #33255

Merged
merged 37 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8e49f2c
Add RPC Event Service draft
erwinpan1 Apr 10, 2024
33e93f2
Commit the draft to add_event in post attr change
erwinpan1 Apr 11, 2024
09c4e9a
Add PreAttributeChangeCallback
erwinpan1 Apr 11, 2024
5183df5
Merge commit '33e93f22eb19b3743dfc9bff1307dc2309f9970d'
erwinpan1 Apr 14, 2024
3252a78
Merge commit '09c4e9a1af0a19f59961c2a14afba9a91c7975b6'
erwinpan1 Apr 14, 2024
8480b14
Support write events as string through RPC
erwinpan1 Apr 15, 2024
de798bb
Revert Chef stubs.cpp to not using AttributeDelegate
erwinpan1 Apr 15, 2024
a104eb4
RPC can call delegate to SwitchManager/EventHandler
erwinpan1 Apr 15, 2024
aa2d923
Rmove ununsed RPC command delegate
erwinpan1 Apr 15, 2024
ff12ada
Rename RPC Event to RPC Actions
erwinpan1 Apr 26, 2024
c952a9a
Simplify RPC code by setting transparent subscribe
erwinpan1 Apr 26, 2024
7e13df1
Chef RPC Actions Draft done.
erwinpan1 Apr 26, 2024
0ea42c4
Fix timer bug, remove unused comments
erwinpan1 Apr 27, 2024
a66c941
Add Latching Switch taglist to Descriptor Cluster
erwinpan1 Apr 27, 2024
5ace910
Cross platform built on ESP32/nRFConnect done
erwinpan1 May 1, 2024
07d6f9f
Update Generic Switch 1
erwinpan1 May 1, 2024
a08814b
Add 2nd Generic Switch
erwinpan1 May 1, 2024
011b71d
Add chef/common/chef-descriptor-namespace.h
erwinpan1 May 1, 2024
11d5e23
Remote printf
erwinpan1 May 1, 2024
6fea707
Remove TODO
erwinpan1 May 1, 2024
6d34fda
Remove unused comments
erwinpan1 May 1, 2024
b0bd550
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 1, 2024
02da45b
Restyled by whitespace
restyled-commits May 1, 2024
422015f
Restyled by clang-format
restyled-commits May 1, 2024
a497bd3
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 2, 2024
5c7b946
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 16, 2024
fd15ba9
Fix according to PR comments
erwinpan1 May 17, 2024
80fd884
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 17, 2024
addca91
Restyled by clang-format
restyled-commits May 17, 2024
b405966
Fix compilation issues
erwinpan1 May 17, 2024
4fbe544
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 17, 2024
adefbfc
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 17, 2024
aec7ebf
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 18, 2024
9ce69df
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 20, 2024
8d6192a
Remove unused debugging codes
erwinpan1 May 23, 2024
d75303c
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 23, 2024
3b83a16
Merge branch 'master' into 0415_add_rpc_event
erwinpan1 May 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions examples/chef/common/chef-descriptor-namespace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
*
* Copyright (c) 2024 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.
*/

#pragma once

// Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces
constexpr const uint8_t kNamespaceCommonLevel = 5;
// Common Number Namespace: 5, tag 0 (Low)
constexpr const uint8_t kTagCommonLow = 0;
// Common Number Namespace: 5, tag 1 (Medium)
constexpr const uint8_t kTagCommonMedium = 1;
// Common Number Namespace: 5, tag 2 (High)
constexpr const uint8_t kTagCommonHigh = 2;

constexpr const uint8_t kNamespaceCommonNumber = 7;
// Common Number Namespace: 7, tag 0 (Zero)
constexpr const uint8_t kTagCommonZero = 0;
// Common Number Namespace: 7, tag 1 (One)
constexpr const uint8_t kTagCommonOne = 1;
// Common Number Namespace: 7, tag 2 (Two)
constexpr const uint8_t kTagCommonTwo = 2;

constexpr const uint8_t kNamespacePosition = 8;
// Common Position Namespace: 8, tag: 0 (Left)
constexpr const uint8_t kTagPositionLeft = 0;
// Common Position Namespace: 8, tag: 1 (Right)
constexpr const uint8_t kTagPositionRight = 1;
// Common Position Namespace: 8, tag: 2 (Top)
constexpr const uint8_t kTagPositionTop = 2;
// Common Position Namespace: 8, tag: 3 (Bottom)
constexpr const uint8_t kTagPositionBottom = 3;
// Common Position Namespace: 8, tag: 4 (Middle)
constexpr const uint8_t kTagPositionMiddle = 4;
// Common Position Namespace: 8, tag: 5 (Row)
constexpr const uint8_t kTagPositionRow = 5;
// Common Position Namespace: 8, tag: 6 (Column)
constexpr const uint8_t kTagPositionColumn = 6;
159 changes: 159 additions & 0 deletions examples/chef/common/chef-rpc-actions-worker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
*
* Copyright (c) 2024 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 "chef-rpc-actions-worker.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/callback.h>
#include <app/data-model/Nullable.h>
#include <app/util/config.h>
#include <lib/core/DataModelTypes.h>
#include <map>
#include <platform/CHIPDeviceLayer.h>

using chip::app::DataModel::Nullable;

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::rpc;

static std::map<ClusterId, ActionsDelegate *> gActionsDelegateMap{};

ActionsDelegate * RpcFindActionsDelegate(ClusterId clusterId)
{
if (gActionsDelegateMap.find(clusterId) != gActionsDelegateMap.end())
{
return gActionsDelegateMap[clusterId];
}

return nullptr;
}

static void RpcActionsTaskCallback(System::Layer * systemLayer, void * data)
{
ChefRpcActionsWorker * worker = (ChefRpcActionsWorker *) data;

worker->ProcessActionQueue();
}

bool ChefRpcActionsCallback(EndpointId endpointId, ClusterId clusterId, uint8_t type, uint32_t delayMs, uint32_t actionId,
std::vector<uint32_t> args)
{
ActionTask task(endpointId, clusterId, static_cast<ActionType>(type), delayMs, actionId, args);

return ChefRpcActionsWorker::Instance().EnqueueAction(task);
}

bool ChefRpcActionsWorker::EnqueueAction(ActionTask task)
{
bool kickTimer = false;

if (queue.empty())
{
kickTimer = true; // kick timer when the first task is adding to the queue
}

queue.push(task);

if (kickTimer)
{
(void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(task.delayMs), RpcActionsTaskCallback, this);
}
return true;
}

void ChefRpcActionsWorker::ProcessActionQueue()
{
// Dequeue the first item
ActionTask task = queue.front();
queue.pop();

ActionsDelegate * delegate = RpcFindActionsDelegate(task.clusterId);
if (nullptr == delegate)
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved
{
ChipLogError(NotSpecified,
"Cannot run action due to not finding delegate: endpointId=%d, clusterId=%04lx, attributeId=%04lx \033[0m \n",
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved
task.endpointId, static_cast<unsigned long>(task.clusterId), static_cast<unsigned long>(task.actionId));
}
else
{
ActionType type = static_cast<ActionType>(task.type);

switch (type)
{
case ActionType::WRITE_ATTRIBUTE: {
ChipLogProgress(NotSpecified, "Writing Attribute: endpointId=%d, clusterId=%04lx, attributeId=%04lx, args.size=%lu",
task.endpointId, static_cast<unsigned long>(task.clusterId), static_cast<unsigned long>(task.actionId),
static_cast<unsigned long>(task.args.size()));
delegate->AttributeWriteHandler(task.endpointId, static_cast<chip::AttributeId>(task.actionId), task.args);
}
break;
case ActionType::RUN_COMMAND: {
ChipLogProgress(NotSpecified, "Running Command: endpointId=%d, clusterId=%04lx, commandId=%04lx, args.size=%lu",
task.endpointId, static_cast<unsigned long>(task.clusterId), static_cast<unsigned long>(task.actionId),
static_cast<unsigned long>(task.args.size()));
delegate->CommandHandler(task.endpointId, static_cast<chip::CommandId>(task.actionId), task.args);
}
break;
case ActionType::EMIT_EVENT: {
ChipLogProgress(NotSpecified, "Emitting Event: endpointId=%d, clusterId=%04lx, eventIdId=%04lx, args.size=%lu",
task.endpointId, static_cast<unsigned long>(task.clusterId), static_cast<unsigned long>(task.actionId),
static_cast<unsigned long>(task.args.size()));
delegate->EventHandler(task.endpointId, static_cast<chip::EventId>(task.actionId), task.args);
}
break;
default:
break;
}
}

if (queue.empty())
{
// Return due to no more actions in queue
return;
}

// Run next action
task = queue.front();
ChipLogProgress(NotSpecified, "StartTimer: endpointId=%d, clusterId=%04lx, eventIdId=%04lx, task.delyMs=%lu", task.endpointId,
static_cast<unsigned long>(task.clusterId), static_cast<unsigned long>(task.actionId),
static_cast<unsigned long>(task.delayMs));
(void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(task.delayMs), RpcActionsTaskCallback, this);
}

void ChefRpcActionsWorker::RegisterRpcActionsDelegate(ClusterId clusterId, ActionsDelegate * delegate)
{
// Register by cluster
if (nullptr == RpcFindActionsDelegate(clusterId))
{
gActionsDelegateMap[clusterId] = delegate;
return;
}
}

ChefRpcActionsWorker::ChefRpcActionsWorker()
{
chip::rpc::SubscribeActions(ChefRpcActionsCallback);
}

static ChefRpcActionsWorker instance;

ChefRpcActionsWorker & ChefRpcActionsWorker::Instance()
{
return instance;
}
77 changes: 77 additions & 0 deletions examples/chef/common/chef-rpc-actions-worker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
*
* Copyright (c) 2024 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/clusters/mode-base-server/mode-base-server.h>
#include <app/util/config.h>
#include <cstring>
#include <queue>
#include <utility>
#include <vector>

#include "Rpc.h"

namespace chip {
namespace app {

class ActionsDelegate
{
public:
ActionsDelegate(ClusterId clusterId) : mClusterId(clusterId){};

virtual ~ActionsDelegate() = default;

virtual void AttributeWriteHandler(chip::EndpointId endpointId, chip::AttributeId attributeId, std::vector<uint32_t> args){};
virtual void CommandHandler(chip::EndpointId endpointId, chip::CommandId commandId, std::vector<uint32_t> args){};
virtual void EventHandler(chip::EndpointId endpointId, chip::EventId eventId, std::vector<uint32_t> args){};
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved

protected:
ClusterId mClusterId;
};

struct ActionTask
{
chip::EndpointId endpointId;
chip::ClusterId clusterId;
chip::rpc::ActionType type; // Aligned with Storage buf
uint32_t delayMs;
uint32_t actionId;
std::vector<uint32_t> args;
ActionTask(chip::EndpointId e, chip::ClusterId c, chip::rpc::ActionType t, uint32_t d, uint32_t i, std::vector<uint32_t> a) :
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved
endpointId(e), clusterId(c), type(t), delayMs(d), actionId(i), args(a){};
~ActionTask(){};
};

class ChefRpcActionsWorker
{
public:
static ChefRpcActionsWorker & Instance();

ChefRpcActionsWorker();

bool EnqueueAction(ActionTask task);
void ProcessActionQueue();
void RegisterRpcActionsDelegate(ClusterId clusterId, ActionsDelegate * delegate);

private:
std::queue<ActionTask> queue;
};

} // namespace app
} // namespace chip
88 changes: 88 additions & 0 deletions examples/chef/common/clusters/switch/SwitchEventHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
*
* Copyright (c) 2022 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 <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/switch-server/switch-server.h>
#include <app/server/Server.h>
#include <app/util/att-storage.h>
#include <platform/PlatformManager.h>

#include "SwitchEventHandler.h"

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::Switch;
using namespace chip::DeviceLayer;

void SwitchEventHandler::OnSwitchLatched(EndpointId endpointId, uint8_t newPosition)
{
ChipLogDetail(NotSpecified, "The latching switch is moved to a new position:%d", newPosition);

Clusters::SwitchServer::Instance().OnSwitchLatch(endpointId, newPosition);
}

void SwitchEventHandler::OnInitialPress(EndpointId endpointId, uint8_t newPosition)
{
ChipLogDetail(NotSpecified, "The new position when the momentary switch starts to be pressed:%d", newPosition);

Clusters::SwitchServer::Instance().OnInitialPress(endpointId, newPosition);
}

void SwitchEventHandler::OnLongPress(EndpointId endpointId, uint8_t newPosition)
{
ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed for a long time:%d", newPosition);

Clusters::SwitchServer::Instance().OnLongPress(endpointId, newPosition);
}

void SwitchEventHandler::OnShortRelease(EndpointId endpointId, uint8_t previousPosition)
{
ChipLogDetail(NotSpecified, "The the previous value of the CurrentPosition when the momentary switch has been released:%d",
previousPosition);

Clusters::SwitchServer::Instance().OnShortRelease(endpointId, previousPosition);
}

void SwitchEventHandler::OnLongRelease(EndpointId endpointId, uint8_t previousPosition)
{
ChipLogDetail(NotSpecified,
"The the previous value of the CurrentPosition when the momentary switch has been released after having been "
"pressed for a long time:%d",
previousPosition);

Clusters::SwitchServer::Instance().OnLongRelease(endpointId, previousPosition);
}

void SwitchEventHandler::OnMultiPressOngoing(EndpointId endpointId, uint8_t newPosition, uint8_t count)
{
ChipLogDetail(NotSpecified, "The new position when the momentary switch has been pressed in a multi-press sequence:%d",
newPosition);
ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count);

Clusters::SwitchServer::Instance().OnMultiPressOngoing(endpointId, newPosition, count);
}

void SwitchEventHandler::OnMultiPressComplete(EndpointId endpointId, uint8_t previousPosition, uint8_t count)
{
ChipLogDetail(NotSpecified, "The previous position when the momentary switch has been pressed in a multi-press sequence:%d",
previousPosition);
ChipLogDetail(NotSpecified, "%d times the momentary switch has been pressed", count);
erwinpan1 marked this conversation as resolved.
Show resolved Hide resolved

Clusters::SwitchServer::Instance().OnMultiPressComplete(endpointId, previousPosition, count);
}
Loading
Loading