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

Basic data model structure #1468

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
10e1df4
Prefix simulated datamodel with 'App' to avoid conflicts
kedars Jul 10, 2020
4cca13d
Create baseline classes for 'Value' and 'Attribute'
kedars Jul 2, 2020
3d409c8
Use enum instead of template
kedars Jul 3, 2020
eb9c412
Get a basic Cluster Server structure
kedars Jul 5, 2020
a43a2c9
Let LEDWidget class in wifi-echo implement the OnOff Cluster
kedars Jul 7, 2020
ed27179
Restyled by clang-format
restyled-commits Jul 7, 2020
dc2f1d9
Fix incorrect data type
kedars Jul 7, 2020
1e4612c
Endpoint 0 is reserved
kedars Jul 8, 2020
2a33054
Eliminate CHIP prefix from the datatype/function names
kedars Jul 8, 2020
71f575f
Move to lib/datamodel from lib/core
kedars Jul 8, 2020
825133e
Use a static allocation of the Basic Cluster instead of on the heap
kedars Jul 8, 2020
8ef76bf
add skeleton tests directory, tweaks to make system
Jul 8, 2020
3424e9e
fixup
Jul 8, 2020
d4e4f54
remove CHIP for files that live in datamodel/ subdir
Jul 8, 2020
5fd8f44
more little renames
Jul 8, 2020
16d7861
Add tests for ClusterServer
kedars Jul 9, 2020
19133b5
Use CHIPError.h for errors
kedars Jul 9, 2020
9b5a74d
Move standard clusters in their own files
kedars Jul 9, 2020
679cc6b
Documentation updates
kedars Jul 9, 2020
5eee74d
Missed the change in the test file
kedars Jul 9, 2020
725ddca
* add Deque.h
Jul 10, 2020
300cf24
fixups
Jul 10, 2020
8e8e293
add documentation
Jul 10, 2020
adfc032
Minor fixes
kedars Jul 10, 2020
38ef849
Include Dequeue.h to the build system
kedars Jul 10, 2020
bc6f68e
Fix tests
kedars Jul 10, 2020
b520ca1
Restyled fixes
restyled-commits Jul 10, 2020
d2178f4
Add 'gn' support
kedars Jul 10, 2020
f878cec
Fixes from review feedback
kedars Jul 11, 2020
94c7525
include lib/datamodel/.. -> include datamodel/...
Jul 13, 2020
087e036
Move the ZCLVersion/StackVersion within the SDK
kedars Jul 14, 2020
8a84cfb
restyle
kedars Jul 14, 2020
3e390b8
functor instead of std::function
Jul 15, 2020
4901e06
Use 'g' prefix for globals
kedars Jul 19, 2020
41fe827
Introduce ClusterId_t and AttributeId_t
kedars Jul 19, 2020
f42189d
Don't embed 'enum' or min/max in the Attribute class
kedars Jul 21, 2020
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
2 changes: 2 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") {
"${chip_root}/src/inet",
"${chip_root}/src/lib",
"${chip_root}/src/lib/core",
"${chip_root}/src/lib/datamodel",
"${chip_root}/src/lib/shell",
"${chip_root}/src/lib/support",
"${chip_root}/src/lwip:all",
Expand Down Expand Up @@ -73,6 +74,7 @@ if (current_toolchain != "${dir_pw_toolchain}/dummy:dummy") {
"${chip_root}/src/crypto/tests",
"${chip_root}/src/inet/tests",
"${chip_root}/src/lib/core/tests",
"${chip_root}/src/lib/datamodel/tests",
"${chip_root}/src/lib/support/tests",
"${chip_root}/src/lwip/tests",
"${chip_root}/src/platform/tests",
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2231,6 +2231,8 @@ src/inet/Makefile
src/inet/tests/Makefile
src/lib/Makefile
src/lib/core/tests/Makefile
src/lib/datamodel/Makefile
src/lib/datamodel/tests/Makefile
src/lib/shell/Makefile
src/lib/shell/tests/Makefile
src/lib/support/Makefile
Expand Down
21 changes: 8 additions & 13 deletions examples/wifi-echo/server/esp32/main/EchoDeviceCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "EchoDeviceCallbacks.h"
#include "esp_log.h"
#include <datamodel/ClusterServer.h>
#include <platform/CHIPDeviceLayer.h>
#include <support/CodeUtils.h>

Expand All @@ -34,6 +35,7 @@
static const char * TAG = "echo-devicecallbacks";
using namespace ::chip::Inet;
using namespace ::chip::DeviceLayer;
using namespace ::chip::DataModel;

extern LEDWidget statusLED; // In wifi-echo.cpp

Expand Down Expand Up @@ -70,22 +72,15 @@ void EchoDeviceCallbacks::DeviceEventCallback(const ChipDeviceEvent * event, int
}
}

extern ClusterServer gServer;
/* This function can be eliminated, and instead its contents will get executed */
void EchoDeviceCallbacks::PostAttributeChangeCallback(uint8_t endpoint, ChipZclClusterId clusterId, ChipZclAttributeId attributeId,
uint8_t mask, uint16_t manufacturerCode, uint8_t type, uint8_t size,
uint8_t * value)
{
if (clusterId != CHIP_ZCL_CLUSTER_ON_OFF)
{
ESP_LOGI(TAG, "Unknown cluster ID: %d", clusterId);
return;
}

if (attributeId != CHIP_ZCL_CLUSTER_ON_OFF_SERVER_ATTRIBUTE_ON_OFF)
{
ESP_LOGI(TAG, "Unknown attribute ID: %d", attributeId);
return;
}
ESP_LOGI(TAG, "Got the post attribute callback");
// At this point we can assume that value points to a boolean value.
statusLED.Set(*value);
Value cValue(kCHIPValueType_Bool);
memcpy((void *) &cValue.Int64, (void *) value, size);

gServer.SetValue(endpoint, clusterId, attributeId, cValue);
}
16 changes: 15 additions & 1 deletion examples/wifi-echo/server/esp32/main/LEDWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#include <datamodel/ClusterOnOff.h>

#if CONFIG_HAVE_DISPLAY
// The Y position of the LED Status message on screen as a
Expand All @@ -46,7 +47,7 @@ static const char * onMsg = "LIGHT: ON";
static const char * offMsg = "LIGHT: OFF";

#endif

using namespace ::chip::DataModel;
extern const char * TAG;

void LEDWidget::Init(gpio_num_t gpioNum)
Expand All @@ -71,6 +72,19 @@ void LEDWidget::Set(bool state)
{
mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
DoSet(state);
Cluster::Set(kAttributeIdOnOff, ValueBool(state));
}

CHIP_ERROR LEDWidget::Set(uint16_t attrId, const Value & value)
{
if (attrId == kAttributeIdOnOff)
{
printf("Setting value to %d\n", ValueToBool(value));
DoSet(ValueToBool(value));
/* Update our internal data model as well */
Cluster::Set(attrId, value);
}
return CHIP_NO_ERROR;
}

void LEDWidget::Blink(uint32_t changeRateMS)
Expand Down
4 changes: 3 additions & 1 deletion examples/wifi-echo/server/esp32/main/include/LEDWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include <datamodel/ClusterOnOff.h>

class LEDWidget
class LEDWidget : public chip::DataModel::ClusterOnOff
{
public:
void Init(gpio_num_t gpioNum);
void Set(bool state);
int Set(uint16_t attrId, const chip::DataModel::Value & value);
void Blink(uint32_t changeRateMS);
void Blink(uint32_t onTimeMS, uint32_t offTimeMS);
void BlinkOnError();
Expand Down
55 changes: 44 additions & 11 deletions examples/wifi-echo/server/esp32/main/wifi-echo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
#include <vector>

#include <crypto/CHIPCryptoPAL.h>
#include <datamodel/ClusterServer.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <support/ErrorStr.h>
#include <transport/SecureSessionMgr.h>

using namespace ::chip;
using namespace ::chip::DeviceLayer;
using namespace ::chip::DataModel;

extern void startServer();

Expand Down Expand Up @@ -104,44 +106,47 @@ LEDWidget statusLED;
const char * TAG = "wifi-echo-demo";

static EchoDeviceCallbacks EchoCallbacks;
const uint8_t applicationVersion = 20;
const uint8_t HWVersion = 1;
ClusterServer gServer(applicationVersion, HWVersion);

namespace {

std::vector<Button> buttons = { Button(), Button(), Button() };
std::vector<gpio_num_t> button_gpios = { BUTTON_1_GPIO_NUM, BUTTON_2_GPIO_NUM, BUTTON_3_GPIO_NUM };

// Pretend these are devices with endpoints with clusters with attributes
typedef std::tuple<std::string, std::string> Attribute;
typedef std::vector<Attribute> Attributes;
typedef std::tuple<std::string, Attributes> Cluster;
typedef std::vector<Cluster> Clusters;
typedef std::tuple<std::string, Clusters> Endpoint;
typedef std::vector<Endpoint> Endpoints;
typedef std::tuple<std::string, Endpoints> Device;
typedef std::tuple<std::string, std::string> AppAttribute;
typedef std::vector<AppAttribute> AppAttributes;
typedef std::tuple<std::string, AppAttributes> AppCluster;
typedef std::vector<AppCluster> AppClusters;
typedef std::tuple<std::string, AppClusters> AppEndpoint;
typedef std::vector<AppEndpoint> AppEndpoints;
typedef std::tuple<std::string, AppEndpoints> Device;
typedef std::vector<Device> Devices;
Devices devices;

void AddAttribute(std::string name, std::string value)
{
Attribute attribute = std::make_tuple(std::move(name), std::move(value));
AppAttribute attribute = std::make_tuple(std::move(name), std::move(value));
std::get<1>(std::get<1>(std::get<1>(devices.back()).back()).back()).emplace_back(std::move(attribute));
}

void AddCluster(std::string name)
{
Cluster cluster = std::make_tuple(std::move(name), std::move(Attributes()));
AppCluster cluster = std::make_tuple(std::move(name), std::move(AppAttributes()));
std::get<1>(std::get<1>(devices.back()).back()).emplace_back(std::move(cluster));
}

void AddEndpoint(std::string name)
{
Endpoint endpoint = std::make_tuple(std::move(name), std::move(Clusters()));
AppEndpoint endpoint = std::make_tuple(std::move(name), std::move(AppClusters()));
std::get<1>(devices.back()).emplace_back(std::move(endpoint));
}

void AddDevice(std::string name)
{
Device device = std::make_tuple(std::move(name), std::move(Endpoints()));
Device device = std::make_tuple(std::move(name), std::move(AppEndpoints()));
devices.emplace_back(std::move(device));
}

Expand Down Expand Up @@ -352,6 +357,30 @@ std::string createSetupPayload()

} // namespace

void PrintDataModel(ClusterServer & server)
{
printf("Server:\n");
int endpointId = 1;

/* Endpoints */
server.mEndpoints.Foreach([&endpointId](Endpoint * endpoint) -> void {
printf(" EndPoint: %d\n", endpointId++);

/* Clusters */
endpoint->mClusters.Foreach([](Cluster * cluster) -> void {
printf(" ClusterId: 0x%04x\n", cluster->mClusterId);

/* Attributes */
cluster->mAttrs.Foreach([](Attribute * attr) -> void {
printf(" Attribute: 0x%04x\n", attr->mAttrId);
char printstr[20];
attr->Get().ValueToStr(printstr, sizeof(printstr));
printf(" Value: %s\n", printstr);
});
});
});
}

extern "C" void app_main()
{
ESP_LOGI(TAG, "WiFi Echo Demo!");
Expand Down Expand Up @@ -396,6 +425,10 @@ extern "C" void app_main()

statusLED.Init(STATUS_LED_GPIO_NUM);

/* Add a cluster to the primary endpoint of our cluster server */
gServer.AddCluster(&statusLED);
PrintDataModel(gServer);

// Start the Echo Server
InitDataModelHandler();
startServer();
Expand Down
7 changes: 7 additions & 0 deletions src/lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ SUBDIRS = \
shell \
support \
core/tests \
datamodel \
$(NULL)

# Pull in the sources that comprise the CHIP library.
Expand All @@ -37,6 +38,7 @@ include ../inet/InetLayer.am
include ../system/SystemLayer.am
include ../transport/TransportLayer.am
include core/CoreLayer.am
include datamodel/DataModel.am
include support/SupportLayer.am
include profiles/ProfilesLayer.am
include ../crypto/Crypto.am
Expand All @@ -46,6 +48,10 @@ include ../app/DataModel.am
CoreLayer_dir=$(includedir)/core
dist_CoreLayer__HEADERS=$(CHIP_BUILD_CORE_LAYER_HEADER_FILES)

# install headers for datamodel layer
DataModel_dir=$(includedir)/datamodel
dist_DataModel__HEADERS=$(CHIP_BUILD_DATAMODEL_HEADER_FILES)

# install headers for DeviceController
Controller_dir=$(includedir)/controller
dist_Controller__HEADERS=$(CHIP_BUILD_DEVICE_CONTROLLER_HEADER_FILES)
Expand Down Expand Up @@ -73,6 +79,7 @@ libCHIP_a_CPPFLAGS = \
libCHIP_a_SOURCES = $(CHIP_BUILD_SYSTEM_LAYER_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_INET_LAYER_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_CORE_LAYER_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_DATAMODEL_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_SUPPORT_LAYER_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_DEVICE_CONTROLLER_SOURCE_FILES)
libCHIP_a_SOURCES += $(CHIP_BUILD_DATA_MODEL_SOURCE_FILES)
Expand Down
117 changes: 117 additions & 0 deletions src/lib/datamodel/Attribute.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
*
* Copyright (c) 2020 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
* This file contains definitions for working with CHIP Attributes
*
*/

#ifndef CHIP_ATTRIBUTE_H_
#define CHIP_ATTRIBUTE_H_

#include <datamodel/Deque.h>
#include <datamodel/Value.h>

#include <core/CHIPError.h>

namespace chip {
namespace DataModel {

typedef uint16_t AttributeId_t;
/**
* @brief
* This class implements a single attribute.
*/
class Attribute
{
private:
Deque<Attribute> mDeque;
friend class Cluster;

public:
AttributeId_t mAttrId;

Attribute(AttributeId_t attrId) : mDeque(this), mAttrId(attrId) {}

/**
* @brief
* Set this attribute to a value
*
* @param value the new value that this attribute should be updated with
*/
virtual CHIP_ERROR Set(const Value & newValue) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means a vtable pointer for every attribute, as well as extra vtables for each subclass (2 so far).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also type-erased, with Value hiding the actual type of the underlying value element.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With Value being still a union, it means that the caller is still going to pay the penalty of maximal storage when utilizing this API.

This API is no better than just having Set(void *value) - the union inside Value is effectively an opaque data store. In fact, the latter is better since the caller-side allocated storage for the value is exactly as big as the type of the value they're trying to set.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

The other thing to note is that for primitive values that fit in a single register passing them by value produces slightly smaller code than the const reference.


/* Need to define the behaviour when Value contains pointers
* to allocated data
*/
/**
* @brief
* Get the value of this attribute
*
*/
virtual Value Get(void) = 0;
};

template <typename ValueType>
class AttributeSimple : public Attribute
{
private:
ValueType mValue;

public:
AttributeSimple(AttributeId_t attrId) : Attribute(attrId) {}
AttributeSimple(AttributeId_t attrId, ValueType value) : Attribute(attrId), mValue(value) {}

CHIP_ERROR Set(const Value & newValue) { return ValueToType(newValue, mValue); }

Value Get(void) { return TypeToValue(mValue); }
};

template <typename ValueType, ValueType min, ValueType max>
class AttributeWithRange : public Attribute
{
private:
ValueType mValue;
const ValueType mMin = min;
const ValueType mMax = max;

public:
AttributeWithRange(AttributeId_t attrId) : Attribute(attrId) {}
AttributeWithRange(AttributeId_t attrId, ValueType value) : Attribute(attrId), mValue(value) {}

CHIP_ERROR Set(const Value & newValue)
{
ValueType tmp;
if (ValueToType(newValue, tmp) == CHIP_NO_ERROR)
{
if ((tmp >= mMin) && (tmp <= mMax))
{
mValue = tmp;
return CHIP_NO_ERROR;
}
}
return CHIP_ERROR_INTERNAL;
}

Value Get(void) { return TypeToValue(mValue); }
};

} // namespace DataModel
} // namespace chip

#endif /* CHIP_ATTRIBUTE_H_ */
Loading