diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index f83c88729a9b0d..ae62ddc32acf0c 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -125,6 +125,19 @@ include(${PIGWEED_ROOT}/pw_build/pigweed.cmake) include(${PIGWEED_ROOT}/pw_protobuf_compiler/proto.cmake) set(dir_pw_third_party_nanopb "${CHIP_ROOT}/third_party/nanopb/repo" CACHE STRING "" FORCE) +pw_proto_library(attributes_service + SOURCES + ${CHIP_ROOT}/examples/common/pigweed/protos/attributes_service.proto + INPUTS + ${CHIP_ROOT}/examples/common/pigweed/protos/attributes_service.options + PREFIX + attributes_service + STRIP_PREFIX + ${CHIP_ROOT}/examples/common/pigweed/protos + DEPS + pw_protobuf.common_protos +) + pw_proto_library(button_service SOURCES ${CHIP_ROOT}/examples/common/pigweed/protos/button_service.proto @@ -160,6 +173,17 @@ pw_proto_library(lighting_service pw_protobuf.common_protos ) +pw_proto_library(locking_service + SOURCES + ${CHIP_ROOT}/examples/common/pigweed/protos/locking_service.proto + PREFIX + locking_service + STRIP_PREFIX + ${CHIP_ROOT}/examples/common/pigweed/protos + DEPS + pw_protobuf.common_protos +) + pw_proto_library(wifi_service SOURCES ${CHIP_ROOT}/examples/ipv6only-app/common/wifi_service/wifi_service.proto @@ -174,9 +198,11 @@ pw_proto_library(wifi_service ) target_link_libraries(${COMPONENT_LIB} PUBLIC + attributes_service.nanopb_rpc button_service.nanopb_rpc device_service.nanopb_rpc lighting_service.nanopb_rpc + locking_service.nanopb_rpc wifi_service.nanopb_rpc pw_checksum pw_hdlc diff --git a/examples/all-clusters-app/esp32/main/Rpc.cpp b/examples/all-clusters-app/esp32/main/Rpc.cpp index 60377ec2df4d74..0de247455fcd61 100644 --- a/examples/all-clusters-app/esp32/main/Rpc.cpp +++ b/examples/all-clusters-app/esp32/main/Rpc.cpp @@ -27,9 +27,11 @@ #include "pw_log/log.h" #include "pw_rpc/server.h" #include "pw_sys_io/sys_io.h" +#include "rpc_services/Attributes.h" #include "rpc_services/Button.h" #include "rpc_services/Device.h" #include "rpc_services/Lighting.h" +#include "rpc_services/Locking.h" #include @@ -41,6 +43,7 @@ #include "esp_wifi.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" +#include "freertos/timers.h" #include "pw_containers/flat_map.h" #include "pw_status/status.h" #include "pw_status/try.h" @@ -109,10 +112,17 @@ class Esp32Device final : public Device public: pw::Status Reboot(ServerContext & ctx, const pw_protobuf_Empty & request, pw_protobuf_Empty & response) override { - esp_restart(); - // WILL NOT RETURN + mRebootTimer = xTimerCreateStatic("Reboot", kRebootTimerPeriodTicks, false, nullptr, RebootHandler, &mRebootTimerBuffer); + xTimerStart(mRebootTimer, 0); return pw::OkStatus(); } + +private: + static constexpr TickType_t kRebootTimerPeriodTicks = 1000; + TimerHandle_t mRebootTimer; + StaticTimer_t mRebootTimerBuffer; + + static void RebootHandler(TimerHandle_t) { esp_restart(); } }; class Wifi final : public generated::Wifi @@ -300,17 +310,21 @@ constexpr uint8_t kRpcTaskPriority = 5; TaskHandle_t rpcTaskHandle; +Attributes attributes_service; Esp32Button button_service; Esp32Device device_service; Lighting lighting_service; +Locking locking_service; Wifi wifi_service; pw::trace::TraceService trace_service; void RegisterServices(pw::rpc::Server & server) { + server.RegisterService(attributes_service); server.RegisterService(button_service); server.RegisterService(device_service); server.RegisterService(lighting_service); + server.RegisterService(locking_service); server.RegisterService(wifi_service); server.RegisterService(trace_service); PW_TRACE_SET_ENABLED(true); diff --git a/examples/common/pigweed/BUILD.gn b/examples/common/pigweed/BUILD.gn index 7555da42ac8344..2d5b69c1b8d4ce 100644 --- a/examples/common/pigweed/BUILD.gn +++ b/examples/common/pigweed/BUILD.gn @@ -36,6 +36,14 @@ if (chip_enable_pw_rpc) { prefix = "echo_service" } + pw_proto_library("attributes_service") { + sources = [ "protos/attributes_service.proto" ] + inputs = [ "protos/attributes_service.options" ] + deps = [ "$dir_pw_protobuf:common_protos" ] + strip_prefix = "protos" + prefix = "attributes_service" + } + pw_proto_library("device_service") { sources = [ "protos/device_service.proto" ] inputs = [ "protos/device_service.options" ] diff --git a/examples/common/pigweed/protos/attributes_service.options b/examples/common/pigweed/protos/attributes_service.options new file mode 100644 index 00000000000000..35d44b2512175e --- /dev/null +++ b/examples/common/pigweed/protos/attributes_service.options @@ -0,0 +1,2 @@ + +chip.rpc.AttributeData.data_bytes max_size:128 \ No newline at end of file diff --git a/examples/common/pigweed/protos/attributes_service.proto b/examples/common/pigweed/protos/attributes_service.proto new file mode 100644 index 00000000000000..2802c445f36a77 --- /dev/null +++ b/examples/common/pigweed/protos/attributes_service.proto @@ -0,0 +1,98 @@ +syntax = "proto3"; + +import 'pw_protobuf_protos/common.proto'; + +package chip.rpc; + +enum AttributeType { + ZCL_NO_DATA_ATTRIBUTE_TYPE = 0x00; // No data + ZCL_BOOLEAN_ATTRIBUTE_TYPE = 0x10; // Boolean + ZCL_BITMAP8_ATTRIBUTE_TYPE = 0x18; // 8-bit bitmap + ZCL_BITMAP16_ATTRIBUTE_TYPE = 0x19; // 16-bit bitmap + ZCL_BITMAP32_ATTRIBUTE_TYPE = 0x1B; // 32-bit bitmap + ZCL_BITMAP64_ATTRIBUTE_TYPE = 0x1F; // 64-bit bitmap + ZCL_INT8U_ATTRIBUTE_TYPE = 0x20; // Unsigned 8-bit integer + ZCL_INT16U_ATTRIBUTE_TYPE = 0x21; // Unsigned 16-bit integer + ZCL_INT24U_ATTRIBUTE_TYPE = 0x22; // Unsigned 24-bit integer + ZCL_INT32U_ATTRIBUTE_TYPE = 0x23; // Unsigned 32-bit integer + ZCL_INT40U_ATTRIBUTE_TYPE = 0x24; // Unsigned 40-bit integer + ZCL_INT48U_ATTRIBUTE_TYPE = 0x25; // Unsigned 48-bit integer + ZCL_INT56U_ATTRIBUTE_TYPE = 0x26; // Unsigned 56-bit integer + ZCL_INT64U_ATTRIBUTE_TYPE = 0x27; // Unsigned 64-bit integer + ZCL_INT8S_ATTRIBUTE_TYPE = 0x28; // Signed 8-bit integer + ZCL_INT16S_ATTRIBUTE_TYPE = 0x29; // Signed 16-bit integer + ZCL_INT24S_ATTRIBUTE_TYPE = 0x2A; // Signed 24-bit integer + ZCL_INT32S_ATTRIBUTE_TYPE = 0x2B; // Signed 32-bit integer + ZCL_INT40S_ATTRIBUTE_TYPE = 0x2C; // Signed 40-bit integer + ZCL_INT48S_ATTRIBUTE_TYPE = 0x2D; // Signed 48-bit integer + ZCL_INT56S_ATTRIBUTE_TYPE = 0x2E; // Signed 56-bit integer + ZCL_INT64S_ATTRIBUTE_TYPE = 0x2F; // Signed 64-bit integer + ZCL_ENUM8_ATTRIBUTE_TYPE = 0x30; // 8-bit enumeration + ZCL_ENUM16_ATTRIBUTE_TYPE = 0x31; // 16-bit enumeration + ZCL_SINGLE_ATTRIBUTE_TYPE = 0x39; // Single precision + ZCL_DOUBLE_ATTRIBUTE_TYPE = 0x3A; // Double precision + ZCL_OCTET_STRING_ATTRIBUTE_TYPE = 0x41; // Octet String + ZCL_CHAR_STRING_ATTRIBUTE_TYPE = 0x42; // Character String + ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE = 0x43; // Long Octet String + ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE = 0x44; // Long Character String + ZCL_ARRAY_ATTRIBUTE_TYPE = 0x48; // List + ZCL_STRUCT_ATTRIBUTE_TYPE = 0x4C; // Structure + ZCL_TOD_ATTRIBUTE_TYPE = 0xE0; // Time of day + ZCL_DATE_ATTRIBUTE_TYPE = 0xE1; // Date + ZCL_UTC_ATTRIBUTE_TYPE = 0xE2; // UTC Time + ZCL_EPOCH_US_ATTRIBUTE_TYPE = 0xE3; // Epoch Microseconds + ZCL_EPOCH_S_ATTRIBUTE_TYPE = 0xE4; // Epoch Seconds + ZCL_SYSTIME_US_ATTRIBUTE_TYPE = 0xE5; // System Time Microseconds + ZCL_PERCENT_ATTRIBUTE_TYPE = 0xE6; // Percentage units 1% + ZCL_PERCENT100THS_ATTRIBUTE_TYPE = 0xE7; // Percentage units 0.01% + ZCL_CLUSTER_ID_ATTRIBUTE_TYPE = 0xE8; // Cluster ID + ZCL_ATTRIB_ID_ATTRIBUTE_TYPE = 0xE9; // Attribute ID + ZCL_FIELD_ID_ATTRIBUTE_TYPE = 0xEA; // Field ID + ZCL_EVENT_ID_ATTRIBUTE_TYPE = 0xEB; // Event ID + ZCL_COMMAND_ID_ATTRIBUTE_TYPE = 0xEC; // Command ID + ZCL_ACTION_ID_ATTRIBUTE_TYPE = 0xED; // Action ID + ZCL_TRANS_ID_ATTRIBUTE_TYPE = 0xEF; // Transaction ID + ZCL_NODE_ID_ATTRIBUTE_TYPE = 0xF0; // Node ID + ZCL_VENDOR_ID_ATTRIBUTE_TYPE = 0xF1; // Vendor ID + ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE = 0xF2; // Device Type ID + ZCL_FABRIC_ID_ATTRIBUTE_TYPE = 0xF3; // Fabric ID + ZCL_GROUP_ID_ATTRIBUTE_TYPE = 0xF4; // Group ID + ZCL_STATUS_ATTRIBUTE_TYPE = 0xF5; // Status Code + ZCL_DATA_VER_ATTRIBUTE_TYPE = 0xF6; // Data Version + ZCL_EVENT_NO_ATTRIBUTE_TYPE = 0xF7; // Event Number + ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE = 0xF8; // Endpoint Number + ZCL_FABRIC_IDX_ATTRIBUTE_TYPE = 0xF9; // Fabric Index + ZCL_IPADR_ATTRIBUTE_TYPE = 0xFA; // IP Address + ZCL_IPV4ADR_ATTRIBUTE_TYPE = 0xFB; // IPv4 Address + ZCL_IPV6ADR_ATTRIBUTE_TYPE = 0xFC; // IPv6 Address + ZCL_IPV6PRE_ATTRIBUTE_TYPE = 0xFD; // IPv6 Prefix + ZCL_HWADR_ATTRIBUTE_TYPE = 0xFE; // Hardware Address + ZCL_UNKNOWN_ATTRIBUTE_TYPE = 0xFF; // Unknown +} + +message AttributeMetadata { + uint32 endpoint = 1; + uint32 cluster = 2; + uint32 attribute_id = 3; + AttributeType type = 4; +} + +message AttributeData { + oneof data { + bool data_bool = 1; + uint32 data_uint8 = 2; + uint32 data_uint16 = 3; + uint32 data_uint32 = 4; + bytes data_bytes = 5; + }; +} + +message AttributeWrite { + AttributeMetadata metadata = 1; + AttributeData data = 2; +} + +service Attributes { + rpc Write(AttributeWrite) returns (pw.protobuf.Empty){} + rpc Read(AttributeMetadata) returns (AttributeData){} +} \ No newline at end of file diff --git a/examples/common/pigweed/protos/device_service.options b/examples/common/pigweed/protos/device_service.options index be390c39da8d0c..c65bc1155f4757 100644 --- a/examples/common/pigweed/protos/device_service.options +++ b/examples/common/pigweed/protos/device_service.options @@ -1,2 +1,2 @@ - -chip.rpc.DeviceInfo.serial_number max_size:32 // length defined in chip spec 8.2.3.1 \ No newline at end of file +chip.rpc.DeviceInfo.serial_number max_size:32 // length defined in chip spec 8.2.3.1 +chip.rpc.DeviceState.fabric_info max_count:2 \ No newline at end of file diff --git a/examples/common/pigweed/protos/device_service.proto b/examples/common/pigweed/protos/device_service.proto index 7c41e3689987ed..fdca9667a1daf9 100644 --- a/examples/common/pigweed/protos/device_service.proto +++ b/examples/common/pigweed/protos/device_service.proto @@ -4,12 +4,28 @@ package chip.rpc; import 'pw_protobuf_protos/common.proto'; +message PairingInfo { + uint32 code = 1; + uint32 discriminator = 2; +} + // type lengths defined in chip spec 8.2.3.1 message DeviceInfo { uint32 vendor_id = 1; uint32 product_id = 2; uint32 software_version = 3; string serial_number = 4; + PairingInfo pairing_info = 5; +} + +message FabricInfo { + uint32 fabric_id = 1; + uint32 node_id = 2; +} + +message DeviceState { + uint64 time_since_boot_millis = 1; + repeated FabricInfo fabric_info = 2; } service Device { @@ -17,4 +33,6 @@ service Device { rpc Reboot(pw.protobuf.Empty) returns (pw.protobuf.Empty){} rpc TriggerOta(pw.protobuf.Empty) returns (pw.protobuf.Empty){} rpc GetDeviceInfo(pw.protobuf.Empty) returns (DeviceInfo){} + rpc GetDeviceState(pw.protobuf.Empty) returns (DeviceState){} + rpc SetPairingInfo(PairingInfo) returns (pw.protobuf.Empty){} } diff --git a/examples/common/pigweed/rpc_console/py/BUILD.gn b/examples/common/pigweed/rpc_console/py/BUILD.gn index 5ff9c5e13110d8..a9fa6b5797b58e 100644 --- a/examples/common/pigweed/rpc_console/py/BUILD.gn +++ b/examples/common/pigweed/rpc_console/py/BUILD.gn @@ -36,6 +36,7 @@ pw_python_package("chip_rpc") { "$dir_pw_log_tokenized/py", "$dir_pw_protobuf_compiler/py", "$dir_pw_rpc/py", + "${chip_root}/examples/common/pigweed:attributes_service.python", "${chip_root}/examples/common/pigweed:button_service.python", "${chip_root}/examples/common/pigweed:device_service.python", "${chip_root}/examples/common/pigweed:echo_service.python", diff --git a/examples/common/pigweed/rpc_console/py/chip_rpc/console.py b/examples/common/pigweed/rpc_console/py/chip_rpc/console.py index 06d2390b3247e8..45d3b669f79455 100644 --- a/examples/common/pigweed/rpc_console/py/chip_rpc/console.py +++ b/examples/common/pigweed/rpc_console/py/chip_rpc/console.py @@ -51,6 +51,7 @@ from pw_hdlc.rpc import HdlcRpcClient, default_channels # Protos +from attributes_service import attributes_service_pb2 from button_service import button_service_pb2 from device_service import device_service_pb2 from lighting_service import lighting_service_pb2 @@ -66,6 +67,7 @@ SOCKET_PORT = 33000 PROTOS = [button_service_pb2, + attributes_service_pb2, lighting_service_pb2, locking_service_pb2, wifi_service_pb2, diff --git a/examples/common/pigweed/rpc_services/Attributes.h b/examples/common/pigweed/rpc_services/Attributes.h new file mode 100644 index 00000000000000..58dd977adf3afa --- /dev/null +++ b/examples/common/pigweed/rpc_services/Attributes.h @@ -0,0 +1,176 @@ +/* + * + * Copyright (c) 2021 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/util/attribute-storage.h" +#include "attributes_service/attributes_service.rpc.pb.h" +#include "pigweed/rpc_services/internal/StatusUtils.h" +#include +#include +#include + +namespace chip { +namespace rpc { + +// Implementation class for chip.rpc.Attributes. +class Attributes : public generated::Attributes +{ +public: + ::pw::Status Write(ServerContext &, const chip_rpc_AttributeWrite & request, pw_protobuf_Empty & response) + { + const void * data; + switch (request.data.which_data) + { + case chip_rpc_AttributeData_data_bool_tag: + data = &request.data.data.data_bool; + break; + case chip_rpc_AttributeData_data_uint8_tag: + data = &request.data.data.data_uint8; + break; + case chip_rpc_AttributeData_data_uint16_tag: + data = &request.data.data.data_uint16; + break; + case chip_rpc_AttributeData_data_uint32_tag: + data = &request.data.data.data_uint32; + break; + case chip_rpc_AttributeData_data_bytes_tag: + data = &request.data.data.data_bytes; + break; + default: + return pw::Status::InvalidArgument(); + } + RETURN_STATUS_IF_NOT_OK( + emberAfWriteServerAttribute(request.metadata.endpoint, request.metadata.cluster, request.metadata.attribute_id, + const_cast(static_cast(data)), request.metadata.type)); + return pw::OkStatus(); + } + + ::pw::Status Read(ServerContext &, const chip_rpc_AttributeMetadata & request, chip_rpc_AttributeData & response) + { + void * data; + size_t size = 0; + switch (request.type) + { + case chip_rpc_AttributeType_ZCL_BOOLEAN_ATTRIBUTE_TYPE: + data = &response.data.data_bool; + size = sizeof(response.data.data_bool); + response.which_data = chip_rpc_AttributeData_data_bool_tag; + break; + case chip_rpc_AttributeType_ZCL_ENUM8_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_BITMAP8_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT8U_ATTRIBUTE_TYPE: + data = &response.data.data_uint8; + size = sizeof(response.data.data_uint8); + response.which_data = chip_rpc_AttributeData_data_uint8_tag; + break; + case chip_rpc_AttributeType_ZCL_ENUM16_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_BITMAP16_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT16U_ATTRIBUTE_TYPE: + data = &response.data.data_uint16; + size = sizeof(response.data.data_uint16); + response.which_data = chip_rpc_AttributeData_data_uint16_tag; + break; + case chip_rpc_AttributeType_ZCL_BITMAP32_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT32U_ATTRIBUTE_TYPE: + data = &response.data.data_uint32; + size = sizeof(response.data.data_uint32); + response.which_data = chip_rpc_AttributeData_data_uint32_tag; + break; + case chip_rpc_AttributeType_ZCL_ARRAY_ATTRIBUTE_TYPE: + data = response.data.data_bytes.bytes; + size = sizeof(response.data.data_bytes.bytes); + RETURN_STATUS_IF_NOT_OK(emberAfReadServerAttribute(request.endpoint, request.cluster, request.attribute_id, + static_cast(data), size)); + size = emberAfAttributeValueListSize(request.cluster, request.attribute_id, (const uint8_t *) data); + response.data.data_bytes.size = size; + response.which_data = chip_rpc_AttributeData_data_bytes_tag; + return pw::OkStatus(); + case chip_rpc_AttributeType_ZCL_BITMAP64_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT24U_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT40U_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT48U_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT56U_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT64U_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT8S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT16S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT24S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT32S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT40S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT48S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT56S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_INT64S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_SINGLE_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_DOUBLE_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_OCTET_STRING_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_CHAR_STRING_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_LONG_OCTET_STRING_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_LONG_CHAR_STRING_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_STRUCT_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_TOD_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_DATE_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_UTC_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_EPOCH_US_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_EPOCH_S_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_SYSTIME_US_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_PERCENT_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_PERCENT100THS_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_CLUSTER_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_ATTRIB_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_FIELD_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_EVENT_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_COMMAND_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_ACTION_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_TRANS_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_NODE_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_VENDOR_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_DEVTYPE_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_FABRIC_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_GROUP_ID_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_STATUS_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_DATA_VER_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_EVENT_NO_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_ENDPOINT_NO_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_FABRIC_IDX_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_IPADR_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_IPV4ADR_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_IPV6ADR_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_IPV6PRE_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_HWADR_ATTRIBUTE_TYPE: + data = response.data.data_bytes.bytes; + size = emberAfGetDataSize(request.type); + if (size > sizeof(response.data.data_bytes.bytes)) + { + return pw::Status::OutOfRange(); + } + response.data.data_bytes.size = size; + response.which_data = chip_rpc_AttributeData_data_bytes_tag; + break; + case chip_rpc_AttributeType_ZCL_NO_DATA_ATTRIBUTE_TYPE: + case chip_rpc_AttributeType_ZCL_UNKNOWN_ATTRIBUTE_TYPE: + default: + return pw::Status::InvalidArgument(); + } + RETURN_STATUS_IF_NOT_OK(emberAfReadServerAttribute(request.endpoint, request.cluster, request.attribute_id, + static_cast(data), size)); + return pw::OkStatus(); + } +}; + +} // namespace rpc +} // namespace chip diff --git a/examples/common/pigweed/rpc_services/Device.h b/examples/common/pigweed/rpc_services/Device.h index e6e483b0090580..32b143a584b365 100644 --- a/examples/common/pigweed/rpc_services/Device.h +++ b/examples/common/pigweed/rpc_services/Device.h @@ -20,8 +20,11 @@ #include +#include "app/server/Server.h" #include "device_service/device_service.rpc.pb.h" #include "platform/ConfigurationManager.h" +#include "platform/PlatformManager.h" +#include "transport/FabricTable.h" namespace chip { namespace rpc { @@ -48,12 +51,71 @@ class Device : public generated::Device return pw::Status::Unimplemented(); } + virtual pw::Status GetDeviceState(ServerContext &, const pw_protobuf_Empty & request, chip_rpc_DeviceState & response) + { + uint64_t time_since_boot_sec; + DeviceLayer::PlatformMgr().GetUpTime(time_since_boot_sec); + response.time_since_boot_millis = time_since_boot_sec * 1000; + size_t count = 0; + for (const FabricInfo & fabricInfo : Server::GetInstance().GetFabricTable()) + { + if (count < ArraySize(response.fabric_info) && fabricInfo.IsInitialized()) + { + response.fabric_info[count].fabric_id = fabricInfo.GetFabricId(); + response.fabric_info[count].node_id = fabricInfo.GetPeerId().GetNodeId(); + count++; + } + } + response.fabric_info_count = count; + return pw::OkStatus(); + } + virtual pw::Status GetDeviceInfo(ServerContext &, const pw_protobuf_Empty & request, chip_rpc_DeviceInfo & response) { - response.vendor_id = CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID; - response.product_id = CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID; - response.software_version = CHIP_DEVICE_CONFIG_DEVICE_FIRMWARE_REVISION; - snprintf(response.serial_number, sizeof(response.serial_number), CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER); + uint16_t vendor_id; + if (DeviceLayer::ConfigurationMgr().GetVendorId(vendor_id) == CHIP_NO_ERROR) + { + response.vendor_id = static_cast(vendor_id); + } + + uint16_t product_id; + if (DeviceLayer::ConfigurationMgr().GetProductId(product_id) == CHIP_NO_ERROR) + { + response.product_id = static_cast(product_id); + } + + uint16_t software_version; + if (DeviceLayer::ConfigurationMgr().GetFirmwareRevision(software_version) == CHIP_NO_ERROR) + { + response.software_version = software_version; + } + + uint32_t code; + if (DeviceLayer::ConfigurationMgr().GetSetupPinCode(code) == CHIP_NO_ERROR) + { + response.pairing_info.code = code; + response.has_pairing_info = true; + } + + uint16_t discriminator; + if (DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(discriminator) == CHIP_NO_ERROR) + { + response.pairing_info.discriminator = static_cast(discriminator); + response.has_pairing_info = true; + } + size_t serial_size; + DeviceLayer::ConfigurationMgr().GetSerialNumber(response.serial_number, sizeof(response.serial_number), serial_size); + + return pw::OkStatus(); + } + + virtual pw::Status SetPairingInfo(ServerContext &, const chip_rpc_PairingInfo & request, pw_protobuf_Empty & response) + { + if (DeviceLayer::ConfigurationMgr().StoreSetupPinCode(request.code) != CHIP_NO_ERROR || + DeviceLayer::ConfigurationMgr().StoreSetupDiscriminator(request.discriminator) != CHIP_NO_ERROR) + { + return pw::Status::Unknown(); + } return pw::OkStatus(); } }; diff --git a/examples/common/pigweed/rpc_services/Lighting.h b/examples/common/pigweed/rpc_services/Lighting.h index 013113254f7ace..61b09ac371c1ab 100644 --- a/examples/common/pigweed/rpc_services/Lighting.h +++ b/examples/common/pigweed/rpc_services/Lighting.h @@ -39,8 +39,7 @@ class Lighting : public generated::Lighting { uint8_t on = request.on; RETURN_STATUS_IF_NOT_OK( - emberAfWriteServerAttribute(1, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &on, ZCL_BOOLEAN_ATTRIBUTE_ID)); - + emberAfWriteServerAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &on, ZCL_BOOLEAN_ATTRIBUTE_ID)); if (mSupportLevel && request.has_level) { // Clip level to max @@ -61,7 +60,6 @@ class Lighting : public generated::Lighting ZCL_COLOR_CONTROL_CURRENT_SATURATION_ATTRIBUTE_ID, &saturation, ZCL_INT8U_ATTRIBUTE_TYPE)); } - return pw::OkStatus(); } @@ -71,8 +69,7 @@ class Lighting : public generated::Lighting uint8_t level; uint8_t hue; uint8_t saturation; - RETURN_STATUS_IF_NOT_OK( - emberAfReadServerAttribute(1, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &on, sizeof(on))); + RETURN_STATUS_IF_NOT_OK(emberAfReadServerAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, &on, sizeof(on))); response.on = on; if (mSupportLevel) diff --git a/examples/lighting-app/efr32/BUILD.gn b/examples/lighting-app/efr32/BUILD.gn index b0fe8ff27d8d2b..dd93106fd3636b 100644 --- a/examples/lighting-app/efr32/BUILD.gn +++ b/examples/lighting-app/efr32/BUILD.gn @@ -130,6 +130,7 @@ efr32_executable("lighting_app") { "$dir_pw_stream:sys_io_stream", "$dir_pw_sys_io", "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", diff --git a/examples/lighting-app/efr32/src/Rpc.cpp b/examples/lighting-app/efr32/src/Rpc.cpp index f2ad1de49f1a29..d7969972530dc1 100644 --- a/examples/lighting-app/efr32/src/Rpc.cpp +++ b/examples/lighting-app/efr32/src/Rpc.cpp @@ -20,6 +20,7 @@ #include "FreeRTOS.h" #include "PigweedLoggerMutex.h" #include "pigweed/RpcService.h" +#include "pigweed/rpc_services/Attributes.h" #include "pigweed/rpc_services/Button.h" #include "pigweed/rpc_services/Device.h" #include "pigweed/rpc_services/Lighting.h" @@ -58,15 +59,17 @@ static TaskHandle_t sRpcTaskHandle; StaticTask_t sRpcTaskBuffer; StackType_t sRpcTaskStack[RPC_TASK_STACK_SIZE]; -chip::rpc::Efr32Button button_service; -chip::rpc::Lighting lighting_service; -chip::rpc::Efr32Device device_service; +Attributes attributes_service; +Efr32Button button_service; +Efr32Device device_service; +Lighting lighting_service; void RegisterServices(pw::rpc::Server & server) { - server.RegisterService(lighting_service); + server.RegisterService(attributes_service); server.RegisterService(button_service); server.RegisterService(device_service); + server.RegisterService(lighting_service); } } // namespace diff --git a/examples/lighting-app/linux/BUILD.gn b/examples/lighting-app/linux/BUILD.gn index 18be8ba767e93d..d17df1c178f627 100644 --- a/examples/lighting-app/linux/BUILD.gn +++ b/examples/lighting-app/linux/BUILD.gn @@ -68,6 +68,7 @@ executable("chip-lighting-app") { "$dir_pw_stream:sys_io_stream", "$dir_pw_sync:mutex", "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc", "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc", diff --git a/examples/lighting-app/linux/Rpc.cpp b/examples/lighting-app/linux/Rpc.cpp index 4574dba9889886..83db190e5fe85a 100644 --- a/examples/lighting-app/linux/Rpc.cpp +++ b/examples/lighting-app/linux/Rpc.cpp @@ -18,6 +18,7 @@ #include "pw_rpc/server.h" #include "pw_rpc_system_server/rpc_server.h" +#include "rpc_services/Attributes.h" #include "rpc_services/Button.h" #include "rpc_services/Device.h" #include "rpc_services/Lighting.h" @@ -29,12 +30,14 @@ namespace rpc { namespace { +chip::rpc::Attributes attribute_service; chip::rpc::Button button_service; chip::rpc::Lighting lighting_service; chip::rpc::Device device_service; void RegisterServices(pw::rpc::Server & server) { + server.RegisterService(attribute_service); server.RegisterService(lighting_service); server.RegisterService(button_service); server.RegisterService(device_service); diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 7992b5d32f45f4..a5df33a082121f 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -106,6 +106,19 @@ add_subdirectory(third_party/connectedhomeip/examples/platform/nrfconnect/pw_sys add_subdirectory(third_party/connectedhomeip/third_party/nanopb/repo) add_subdirectory(third_party/connectedhomeip/third_party/pigweed/repo) +pw_proto_library(attributes_service + SOURCES + ${CHIP_ROOT}/examples/common/pigweed/protos/attributes_service.proto + INPUTS + ${CHIP_ROOT}/examples/common/pigweed/protos/attributes_service.options + PREFIX + attributes_service + STRIP_PREFIX + ${CHIP_ROOT}/examples/common/pigweed/protos + DEPS + pw_protobuf.common_protos +) + pw_proto_library(button_service SOURCES ${CHIP_ROOT}/examples/common/pigweed/protos/button_service.proto @@ -157,6 +170,7 @@ target_include_directories(app PRIVATE ../../common/pigweed/nrfconnect) target_link_libraries(app PRIVATE + attributes_service.nanopb_rpc button_service.nanopb_rpc device_service.nanopb_rpc lighting_service.nanopb_rpc diff --git a/examples/lighting-app/nrfconnect/main/Rpc.cpp b/examples/lighting-app/nrfconnect/main/Rpc.cpp index ba995e3055dcdd..66100e38593f87 100644 --- a/examples/lighting-app/nrfconnect/main/Rpc.cpp +++ b/examples/lighting-app/nrfconnect/main/Rpc.cpp @@ -20,6 +20,7 @@ #include "PigweedLoggerMutex.h" #include "pigweed/RpcService.h" #include "pw_sys_io_nrfconnect/init.h" +#include "rpc_services/Attributes.h" #include "rpc_services/Button.h" #include "rpc_services/Device.h" #include "rpc_services/Lighting.h" @@ -69,15 +70,17 @@ constexpr int kRpcPriority = 5; K_THREAD_STACK_DEFINE(rpc_stack_area, kRpcTaskSize); struct k_thread rpc_thread_data; -chip::rpc::NrfButton button_service; -chip::rpc::Lighting lighting_service; -chip::rpc::NrfDevice device_service; +Attributes attributes_service; +NrfButton button_service; +NrfDevice device_service; +Lighting lighting_service; void RegisterServices(pw::rpc::Server & server) { - server.RegisterService(lighting_service); + server.RegisterService(attributes_service); server.RegisterService(button_service); server.RegisterService(device_service); + server.RegisterService(lighting_service); } } // namespace diff --git a/examples/lighting-app/nrfconnect/rpc.overlay b/examples/lighting-app/nrfconnect/rpc.overlay index 35dd449ca611fb..eac4807039a8d4 100644 --- a/examples/lighting-app/nrfconnect/rpc.overlay +++ b/examples/lighting-app/nrfconnect/rpc.overlay @@ -43,3 +43,6 @@ CONFIG_LOG_MODE_MINIMAL=n CONFIG_LOG_MODE_IMMEDIATE=y CONFIG_LOG_BACKEND_UART=n CONFIG_LOG_BACKEND_RTT=n + +# Increase zephyr tty rx buffer +CONFIG_CONSOLE_GETCHAR_BUFSIZE=128 \ No newline at end of file