From d4a0ab46cf5bb3026fc71327beb1d8144bed896d Mon Sep 17 00:00:00 2001 From: pankore <86098180+pankore@users.noreply.github.com> Date: Fri, 16 Sep 2022 22:12:38 +0800 Subject: [PATCH 01/22] [Ameba] Implement route hook (#22664) * [RouteHook] Implement route hooks to allow communication with thread devices * [Connectivity] Remove disconnection code from ConnectivityManager * [RouteHook] Fix compile error on 8720CM platform * [Restyle] Fix restyling --- .../all-clusters-app/ameba/chip_main.cmake | 4 + .../ameba/main/DeviceCallbacks.cpp | 6 +- .../ameba/route_hook/ameba_route_hook.c | 206 ++++++++++++++++++ .../ameba/route_hook/ameba_route_hook.h | 10 + .../ameba/route_hook/ameba_route_table.c | 175 +++++++++++++++ .../ameba/route_hook/ameba_route_table.h | 76 +++++++ .../Ameba/ConnectivityManagerImpl.cpp | 17 -- 7 files changed, 476 insertions(+), 18 deletions(-) create mode 100644 examples/platform/ameba/route_hook/ameba_route_hook.c create mode 100644 examples/platform/ameba/route_hook/ameba_route_hook.h create mode 100644 examples/platform/ameba/route_hook/ameba_route_table.c create mode 100644 examples/platform/ameba/route_hook/ameba_route_table.h diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 96e025799113af..fc18f2fa9704cd 100755 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -163,6 +163,9 @@ list( ${chip_dir}/examples/all-clusters-app/ameba/main/LEDWidget.cpp ${chip_dir}/examples/all-clusters-app/ameba/main/DsoHack.cpp + ${chip_dir}/examples/platform/ameba/route_hook/ameba_route_hook.c + ${chip_dir}/examples/platform/ameba/route_hook/ameba_route_table.c + ${chip_dir}/examples/providers/DeviceInfoProviderImpl.cpp ) @@ -204,6 +207,7 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/route_hook ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp b/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp index 259ff3d726f529..028dc7ca2a6370 100644 --- a/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp +++ b/examples/all-clusters-app/ameba/main/DeviceCallbacks.cpp @@ -22,8 +22,8 @@ * Implements all the callbacks to the application from the CHIP Stack * **/ -#include "DeviceCallbacks.h" +#include "DeviceCallbacks.h" #include "CHIPDeviceManager.h" #include #include @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,9 @@ void DeviceCallbacks::OnInternetConnectivityChange(const ChipDeviceEvent * event { ChipLogProgress(DeviceLayer, "IPv6 Server ready..."); chip::app::DnssdServer::Instance().StartServer(); + + ChipLogProgress(DeviceLayer, "Initializing route hook..."); + ameba_route_hook_init(); #if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR // Init OTA requestor only when we have gotten IPv6 address if (!isOTAInitialized) diff --git a/examples/platform/ameba/route_hook/ameba_route_hook.c b/examples/platform/ameba/route_hook/ameba_route_hook.c new file mode 100644 index 00000000000000..0be1f71f359934 --- /dev/null +++ b/examples/platform/ameba/route_hook/ameba_route_hook.c @@ -0,0 +1,206 @@ +#include +#include + +#include "ameba_route_hook.h" +#include "ameba_route_table.h" +#include + +#include "lwip/icmp6.h" +#include "lwip/mld6.h" +#include "lwip/netif.h" +#include "lwip/prot/icmp6.h" +#include "lwip/prot/ip6.h" +#include "lwip/prot/nd6.h" +#include "lwip/raw.h" + +typedef struct ameba_route_hook_t +{ + struct netif * netif; + struct raw_pcb * pcb; + struct ameba_route_hook_t * next; +} ameba_route_hook_t; + +PACK_STRUCT_BEGIN +struct rio_header_t +{ + PACK_STRUCT_FLD_8(u8_t type); + PACK_STRUCT_FLD_8(u8_t length); + PACK_STRUCT_FLD_8(u8_t prefix_length); + PACK_STRUCT_FLD_8(u8_t preference); + PACK_STRUCT_FIELD(u32_t route_lifetime); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +typedef struct rio_header_t rio_header_t; + +static ameba_route_hook_t * s_hooks; + +static bool is_self_address(struct netif * netif, const ip6_addr_t * addr) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(netif->ip6_addr); i++) + { + if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && + memcmp(addr->addr, netif_ip6_addr(netif, i)->addr, sizeof(addr->addr)) == 0) + { + return true; + } + } + return false; +} + +static void ra_recv_handler(struct netif * netif, const uint8_t * icmp_payload, uint16_t payload_len, const ip6_addr_t * src_addr) +{ + if (payload_len < sizeof(struct ra_header)) + { + return; + } + icmp_payload += sizeof(struct ra_header); + payload_len -= sizeof(struct ra_header); + + while (payload_len >= 2) + { + uint8_t opt_type = icmp_payload[0]; + uint8_t opt_len = icmp_payload[1] << 3; + + if (opt_type == ND6_OPTION_TYPE_ROUTE_INFO && opt_len >= sizeof(rio_header_t) && !is_self_address(netif, src_addr) && + payload_len >= opt_len) + { + rio_header_t rio_header; + memcpy(&rio_header, icmp_payload, sizeof(rio_header)); + + // skip if prefix is longer than IPv6 address. + if (rio_header.prefix_length > 128) + { + break; + } + uint8_t prefix_len_bytes = (rio_header.prefix_length + 7) / 8; + int8_t preference = -2 * ((rio_header.preference >> 4) & 1) + (((rio_header.preference) >> 3) & 1); + const uint8_t * rio_data = &icmp_payload[sizeof(rio_header_t)]; + uint8_t rio_data_len = opt_len - sizeof(rio_header_t); + + printf("Received RIO\n"); + if (rio_data_len >= prefix_len_bytes) + { + ip6_addr_t prefix; + ameba_route_entry_t route; + + memset(&prefix, 0, sizeof(prefix)); + memcpy(&prefix.addr, rio_data, prefix_len_bytes); + route.netif = netif; + route.gateway = *src_addr; + route.prefix_length = rio_header.prefix_length; + route.prefix = prefix; + route.preference = preference; + route.lifetime_seconds = lwip_ntohl(rio_header.route_lifetime); + printf("prefix %s lifetime %u\n", ip6addr_ntoa(&prefix), route.lifetime_seconds); + if (ameba_route_table_add_route_entry(&route) == NULL) + { + printf("Failed to add route table entry\n"); + } + else + { + printf("Added entry to route table\n"); + } + } + } + icmp_payload += opt_len; + payload_len -= opt_len; + } +} + +static uint8_t icmp6_raw_recv_handler(void * arg, struct raw_pcb * pcb, struct pbuf * p, const ip_addr_t * addr) +{ + uint8_t * icmp_payload = NULL; + uint16_t icmp_payload_len; + struct ip6_hdr * ip6_header = (struct ip6_hdr *) p->payload; + struct icmp6_hdr * icmp6_header; + ip6_addr_t src; + ip6_addr_t dest; + ameba_route_hook_t * hook = (ameba_route_hook_t *) arg; + + memcpy(src.addr, ip6_header->src.addr, sizeof(src.addr)); + memcpy(dest.addr, ip6_header->dest.addr, sizeof(dest.addr)); +#if LWIP_IPV6_SCOPES + src.zone = 0; +#endif + + if (p->tot_len != p->len) + { + printf("Ignore segmented ICMP packet\n"); + return 0; + } + if (p->tot_len <= sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) + { + printf("Ignore invalid ICMP packet\n"); + return 0; + } + if (!ip6_addr_islinklocal(&dest) && !ip6_addr_isallnodes_linklocal(&dest) && !ip6_addr_isallrouters_linklocal(&dest)) + { + return 0; + } + + icmp_payload_len = p->tot_len - sizeof(struct ip6_hdr); + icmp_payload = p->payload + sizeof(struct ip6_hdr); + + icmp6_header = (struct icmp6_hdr *) icmp_payload; + if (icmp6_header->type == ICMP6_TYPE_RA) + { + ra_recv_handler(hook->netif, icmp_payload, icmp_payload_len, &src); + } + return 0; +} + +int8_t ameba_route_hook_init() +{ + struct netif * lwip_netif = &xnetif[0]; + ip_addr_t router_group = IPADDR6_INIT_HOST(0xFF020000, 0, 0, 0x02); + ameba_route_hook_t * hook = NULL; + uint8_t ret = 0; + + if (lwip_netif == NULL) + { + printf("Invalid network interface\n"); + return -1; + } + + for (ameba_route_hook_t * iter = s_hooks; iter != NULL; iter++) + { + if (iter->netif == lwip_netif) + { + printf("Hook already installed on netif, skip...\n"); + return 0; + } + } + + hook = (ameba_route_hook_t *) malloc(sizeof(ameba_route_hook_t)); + if (hook == NULL) + { + printf("Cannot allocate hook\n"); + return -1; + } + + if (mld6_joingroup_netif(lwip_netif, ip_2_ip6(&router_group)) != ERR_OK) + { + printf("Failed to join multicast group\n"); + ret = -1; + goto exit; + } + + hook->netif = lwip_netif; + hook->pcb = raw_new_ip_type(IPADDR_TYPE_V6, IP6_NEXTH_ICMP6); + hook->pcb->flags |= RAW_FLAGS_MULTICAST_LOOP; + hook->pcb->chksum_reqd = 1; + // The ICMPv6 header checksum offset + hook->pcb->chksum_offset = 2; + raw_bind_netif(hook->pcb, lwip_netif); + raw_recv(hook->pcb, icmp6_raw_recv_handler, hook); + hook->next = s_hooks; + s_hooks = hook; + +exit: + if (ret != 0 && hook != NULL) + { + free(hook); + } + return ret; +} diff --git a/examples/platform/ameba/route_hook/ameba_route_hook.h b/examples/platform/ameba/route_hook/ameba_route_hook.h new file mode 100644 index 00000000000000..802c2de5a58a46 --- /dev/null +++ b/examples/platform/ameba/route_hook/ameba_route_hook.h @@ -0,0 +1,10 @@ +#include +#ifdef __cplusplus +extern "C" { +#endif + +int8_t ameba_route_hook_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/platform/ameba/route_hook/ameba_route_table.c b/examples/platform/ameba/route_hook/ameba_route_table.c new file mode 100644 index 00000000000000..8446c42955ab09 --- /dev/null +++ b/examples/platform/ameba/route_hook/ameba_route_table.c @@ -0,0 +1,175 @@ +#include "ameba_route_table.h" +#include + +#include + +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" +#include "lwip/timeouts.h" + +#define MAX_RIO_ROUTE 20 +#define MAX_RIO_TIMEOUT UINT32_MAX / (1000 * 4) // lwIP defined reasonable timeout value + +static ameba_route_entry_t s_route_entries[MAX_RIO_ROUTE]; + +static ameba_route_entry_t * find_route_entry(const ameba_route_entry_t * route_entry) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (s_route_entries[i].netif == route_entry->netif && s_route_entries[i].prefix_length == route_entry->prefix_length && + memcmp(s_route_entries[i].gateway.addr, route_entry->gateway.addr, sizeof(route_entry->gateway.addr)) == 0 && + memcmp(s_route_entries[i].prefix.addr, route_entry->prefix.addr, route_entry->prefix_length / 8) == 0) + { + return &s_route_entries[i]; + } + } + return NULL; +} + +static ameba_route_entry_t * find_empty_route_entry(void) +{ + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + return &s_route_entries[i]; + } + } + return NULL; +} + +static void route_timeout_handler(void * arg) +{ + ameba_route_entry_t * route = (ameba_route_entry_t *) arg; + + ameba_route_table_remove_route_entry(route); +} + +ameba_route_entry_t * ameba_route_table_add_route_entry(const ameba_route_entry_t * route_entry) +{ + if (route_entry == NULL || (route_entry->lifetime_seconds > MAX_RIO_TIMEOUT && route_entry->lifetime_seconds != UINT32_MAX)) + { + return NULL; + } + + ameba_route_entry_t * entry = find_route_entry(route_entry); + + if (entry == NULL) + { + entry = find_empty_route_entry(); + if (entry == NULL) + { + return NULL; + } + entry->netif = route_entry->netif; + entry->gateway = route_entry->gateway; + ip6_addr_assign_zone(&entry->gateway, IP6_UNICAST, entry->netif); + entry->prefix = route_entry->prefix; + entry->prefix_length = route_entry->prefix_length; + } + else + { + sys_untimeout(route_timeout_handler, entry); + } + entry->preference = route_entry->preference; + entry->lifetime_seconds = route_entry->lifetime_seconds; + if (entry->lifetime_seconds != UINT32_MAX) + { + sys_timeout(entry->lifetime_seconds * 1000, route_timeout_handler, entry); + } + return entry; +} + +int8_t ameba_route_table_remove_route_entry(ameba_route_entry_t * route_entry) +{ + if (route_entry < &s_route_entries[0] || route_entry > &s_route_entries[LWIP_ARRAYSIZE(s_route_entries)]) + { + return -1; + } + route_entry->netif = NULL; + for (ameba_route_entry_t * moved = route_entry; moved < &s_route_entries[LWIP_ARRAYSIZE(s_route_entries) - 1]; moved++) + { + *moved = *(moved + 1); + if (moved->netif == NULL) + { + break; + } + } + return 0; +} + +static inline bool is_better_route(const ameba_route_entry_t * lhs, const ameba_route_entry_t * rhs) +{ + if (rhs == NULL) + { + return true; + } + if (lhs == NULL) + { + return false; + } + return (lhs->prefix_length > rhs->prefix_length) || + (lhs->prefix_length == rhs->prefix_length && lhs->preference > rhs->preference); +} + +static inline bool route_match(const ameba_route_entry_t * route, const ip6_addr_t * dest) +{ + return memcmp(dest, route->prefix.addr, route->prefix_length / 8) == 0; +} + +struct netif * lwip_hook_ip6_route(const ip6_addr_t * src, const ip6_addr_t * dest) +{ + ameba_route_entry_t * route = NULL; + + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (route_match(&s_route_entries[i], dest) && is_better_route(&s_route_entries[i], route)) + { + route = &s_route_entries[i]; + } + } + + if (route) + { + return route->netif; + } + else + { + return NULL; + } +} + +const ip6_addr_t * lwip_hook_nd6_get_gw(struct netif * netif, const ip6_addr_t * dest) +{ + ameba_route_entry_t * route = NULL; + + for (size_t i = 0; i < LWIP_ARRAYSIZE(s_route_entries); i++) + { + if (s_route_entries[i].netif == NULL) + { + break; + } + if (s_route_entries[i].netif == netif && route_match(&s_route_entries[i], dest) && + is_better_route(&s_route_entries[i], route)) + { + route = &s_route_entries[i]; + } + } + + if (route) + { + return &route->gateway; + } + else + { + return NULL; + } +} diff --git a/examples/platform/ameba/route_hook/ameba_route_table.h b/examples/platform/ameba/route_hook/ameba_route_table.h new file mode 100644 index 00000000000000..2d1a875e078314 --- /dev/null +++ b/examples/platform/ameba/route_hook/ameba_route_table.h @@ -0,0 +1,76 @@ +#include + +#include "lwip/ip6_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Route table entry + * + */ +typedef struct +{ + ip6_addr_t prefix; + uint8_t prefix_length; + ip6_addr_t gateway; + int8_t preference; + uint32_t lifetime_seconds; + struct netif * netif; +} ameba_route_entry_t; + +/** + * @brief Adds an entry to the route table + * + * @param[in] route_entry The route entry to be added + * + * @return + * - The pointer to the added route entry on success + * - NULL on failure + * + */ +ameba_route_entry_t * ameba_route_table_add_route_entry(const ameba_route_entry_t * route_entry); + +/** + * @brief Removes an entry from the route table + * + * @param[in] route_entry The route entry to be removed + * + * @return + * - 0 + * - -1 The provided route_entry is not in the route table. + * + */ +int8_t ameba_route_table_remove_route_entry(ameba_route_entry_t * route_entry); + +/** + * @brief The lwIP ip6 route hook, called by the lwIP function ip6_route when sending packets. + * + * @param[in] src The source address + * @param[in] dest The destination address + * + * @return + * - The target interface when route found + * - NULL when route not found + * + */ +struct netif * lwip_hook_ip6_route(const ip6_addr_t * src, const ip6_addr_t * dest); + +/** + * @brief The lwIP gateway hook, called by the lwIP when deciding next hop. + * + * @param[in] netif The output network interface + * @param[in] dest The destination address + * + * @return + * - The gateway address when route found + * - NULL when route not found + * + */ +const ip6_addr_t * lwip_hook_nd6_get_gw(struct netif * netif, const ip6_addr_t * dest); + +#ifdef __cplusplus +} +#endif diff --git a/src/platform/Ameba/ConnectivityManagerImpl.cpp b/src/platform/Ameba/ConnectivityManagerImpl.cpp index 8e8af6049e3c38..040471e7745f2a 100644 --- a/src/platform/Ameba/ConnectivityManagerImpl.cpp +++ b/src/platform/Ameba/ConnectivityManagerImpl.cpp @@ -502,23 +502,6 @@ void ConnectivityManagerImpl::DriveStationState() mLastStationConnectFailTime = System::Clock::kZero; OnStationConnected(); } - - // If the WiFi station interface is no longer enabled, or no longer provisioned, - // disconnect the station from the AP, unless the WiFi station mode is currently - // under application control. - if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled && - (mWiFiStationMode != kWiFiStationMode_Enabled || !IsWiFiStationProvisioned())) - { - ChipLogProgress(DeviceLayer, "Disconnecting WiFi station interface"); - err = Internal::AmebaUtils::WiFiDisconnect(); - if (err != CHIP_NO_ERROR) - { - ChipLogError(DeviceLayer, "WiFiDisconnect() failed: %s", err); - return; - } - - ChangeWiFiStationState(kWiFiStationState_Disconnecting); - } } // Otherwise the station interface is NOT connected to an AP, so... From a736e56a58c838563df0721e95bd46e98ccfb089 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 16 Sep 2022 07:15:26 -0700 Subject: [PATCH 02/22] Improve matter gcoverage accuracy by excluding non-core sdk files (#22656) * Improve matter gcoverage accuracy by excluding non-core sdk files * Address review comments --- scripts/build/build/targets.py | 1 + scripts/build/builders/host.py | 8 +++----- scripts/build_coverage.sh | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index ac0ad46642098b..02ef6b7c369bae 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -79,6 +79,7 @@ def Create(self, runner, repository_path: str, output_prefix: str, builder.target = self builder.identifier = self.name builder.output_dir = os.path.join(output_prefix, self.name) + builder.chip_dir = repository_path builder.enable_flashbundle(enable_flashbundle) return builder diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 58f04151c3f5f8..3e299384e2c3da 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -361,19 +361,17 @@ def generate(self): if self.app == HostApp.TESTS and self.use_coverage: self.coverage_dir = os.path.join(self.output_dir, 'coverage') self._Execute(['mkdir', '-p', self.coverage_dir], title="Create coverage output location") - self._Execute(['lcov', '--initial', '--capture', '--directory', os.path.join(self.output_dir, 'obj'), - '--output-file', os.path.join(self.coverage_dir, 'lcov_base.info')], title="Initial coverage baseline") def PreBuildCommand(self): if self.app == HostApp.TESTS and self.use_coverage: self._Execute(['ninja', '-C', self.output_dir, 'default'], title="Build-only") - self._Execute(['lcov', '--initial', '--capture', '--directory', os.path.join(self.output_dir, 'obj'), + self._Execute(['lcov', '--initial', '--capture', '--directory', os.path.join(self.output_dir, 'obj'), '--exclude', os.path.join(self.chip_dir, 'third_party/*'), '--exclude', '/usr/include/*', '--output-file', os.path.join(self.coverage_dir, 'lcov_base.info')], title="Initial coverage baseline") def PostBuildCommand(self): if self.app == HostApp.TESTS and self.use_coverage: - self._Execute(['lcov', '--capture', '--directory', os.path.join(self.output_dir, 'obj'), '--output-file', - os.path.join(self.coverage_dir, 'lcov_test.info')], title="Update coverage") + self._Execute(['lcov', '--capture', '--directory', os.path.join(self.output_dir, 'obj'), '--exclude', os.path.join(self.chip_dir, 'third_party/*'), '--exclude', '/usr/include/*', + '--output-file', os.path.join(self.coverage_dir, 'lcov_test.info')], title="Update coverage") self._Execute(['lcov', '--add-tracefile', os.path.join(self.coverage_dir, 'lcov_base.info'), '--add-tracefile', os.path.join(self.coverage_dir, 'lcov_test.info'), '--output-file', os.path.join(self.coverage_dir, 'lcov_final.info') diff --git a/scripts/build_coverage.sh b/scripts/build_coverage.sh index 441f727b5e6bd8..b7223ce2e4aa0b 100755 --- a/scripts/build_coverage.sh +++ b/scripts/build_coverage.sh @@ -93,7 +93,7 @@ if [ "$skip_gn" == false ]; then fi mkdir -p "$COVERAGE_ROOT" -lcov --initial --capture --directory "$OUTPUT_ROOT/obj" --output-file "$COVERAGE_ROOT/lcov_base.info" -lcov --capture --directory "$OUTPUT_ROOT"/obj --output-file "$COVERAGE_ROOT/lcov_test.info" +lcov --initial --capture --directory "$OUTPUT_ROOT/obj/src" --exclude="$CHIP_ROOT/third_party/*" --exclude=/usr/include/* --output-file "$COVERAGE_ROOT/lcov_base.info" +lcov --capture --directory "$OUTPUT_ROOT/obj/src" --exclude="$CHIP_ROOT/third_party/*" --exclude=/usr/include/* --output-file "$COVERAGE_ROOT/lcov_test.info" lcov --add-tracefile "$COVERAGE_ROOT/lcov_base.info" --add-tracefile "$COVERAGE_ROOT/lcov_test.info" --output-file "$COVERAGE_ROOT/lcov_final.info" genhtml "$COVERAGE_ROOT/lcov_final.info" --output-directory "$COVERAGE_ROOT/html" From 69551a1badffc43a7d1b2dc141373e59c784966c Mon Sep 17 00:00:00 2001 From: jczhang777 <101778393+jczhang777@users.noreply.github.com> Date: Fri, 16 Sep 2022 22:36:06 +0800 Subject: [PATCH 03/22] [BL602] Fix sve2 problems (#22582) * [BL602] Fix sve2 problems * Restyled by whitespace * Restyled by clang-format * Restyled by gn * [BL602] Update readme * call ef_env_set_default to do factory reset * [BL602] Fix code review issues * Restyled by clang-format * [BL602] Delete not use code Co-authored-by: Restyled.io Co-authored-by: wyhong --- .../lighting-app/bouffalolab/bl602/README.md | 2 +- .../bouffalolab/bl602/src/AppTask.cpp | 2 +- .../bouffalolab/bl602/ldscripts/flash_rom.ld | 2 +- .../bouffalolab/BL602/CHIPPlatformConfig.h | 4 ++ .../BL602/ConfigurationManagerImpl.cpp | 1 + .../BL602/DiagnosticDataProviderImpl.cpp | 45 ++++++++++++++++--- .../BL602/NetworkCommissioningDriver.cpp | 27 ++++++++++- .../BL602/OTAImageProcessorImpl.cpp | 2 +- .../bouffalolab/BL602/PlatformManagerImpl.cpp | 3 +- third_party/bouffalolab/bl602/bl602_sdk.gni | 7 +-- third_party/bouffalolab/repo | 2 +- 11 files changed, 78 insertions(+), 19 deletions(-) diff --git a/examples/lighting-app/bouffalolab/bl602/README.md b/examples/lighting-app/bouffalolab/bl602/README.md index 7a42f8f17abbe4..d82959afd7a19d 100644 --- a/examples/lighting-app/bouffalolab/bl602/README.md +++ b/examples/lighting-app/bouffalolab/bl602/README.md @@ -66,7 +66,7 @@ The steps in this document were validated on Ubuntu 18.04 and 20.04. ``` cd third_party/bouffalolab/repo/tools/flash_tool - ./bflb_iot_tool-ubuntu18 --chipname=BL602 --baudrate=115200 --port=/dev/ttyACM0 --pt=chips/bl602/partition/partition_cfg_4M.toml --dts=chips/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts --firmware=../../../../../../out/bl602-light/chip-bl602-lighting-example.bin + ./bflb_iot_tool --chipname=BL602 --baudrate=115200 --port=/dev/ttyACM0 --pt=chips/bl602/partition/partition_cfg_4M.toml --dts=chips/bl602/device_tree/bl_factory_params_IoTKitA_40M.dts --firmware=../../../../../out/bl602-light/chip-bl602-lighting-example.bin ``` ``` diff --git a/examples/lighting-app/bouffalolab/bl602/src/AppTask.cpp b/examples/lighting-app/bouffalolab/bl602/src/AppTask.cpp index 8774b47b123c4a..62bb09cb5b928b 100644 --- a/examples/lighting-app/bouffalolab/bl602/src/AppTask.cpp +++ b/examples/lighting-app/bouffalolab/bl602/src/AppTask.cpp @@ -55,7 +55,7 @@ #define FACTORY_RESET_TRIGGER_TIMEOUT 3000 #define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000 #define APP_EVENT_QUEUE_SIZE 10 -#define APP_TASK_STACK_SIZE (8192) +#define APP_TASK_STACK_SIZE (4096) #define APP_TASK_PRIORITY 2 #define STATUS_LED_GPIO_NUM GPIO_NUM_2 // Use LED1 (blue LED) as status LED on DevKitC diff --git a/examples/platform/bouffalolab/bl602/ldscripts/flash_rom.ld b/examples/platform/bouffalolab/bl602/ldscripts/flash_rom.ld index 1741f6fb671568..0ed6b74099b710 100644 --- a/examples/platform/bouffalolab/bl602/ldscripts/flash_rom.ld +++ b/examples/platform/bouffalolab/bl602/ldscripts/flash_rom.ld @@ -11,7 +11,7 @@ __RFTLV_HEAD1_L = (0x41524150); /* PAPA */ __RAM_START = 0x4200C000; __RAM_END = 0x4200C000 + 256K - __EM_SIZE; /* leave 8K left for BLE */ -__RAM_TCM_LEN = (16K + 16K + 48K + 64K + 64K - 16K); +__RAM_TCM_LEN = (16K + 16K + 48K + 64K + 64K - 16K - 16K); __RAM_WIFI_LEN = (__RAM_END - __RAM_START - __RAM_TCM_LEN); MEMORY diff --git a/src/platform/bouffalolab/BL602/CHIPPlatformConfig.h b/src/platform/bouffalolab/BL602/CHIPPlatformConfig.h index 2a5cfebda28e17..4117d3a1245ca3 100644 --- a/src/platform/bouffalolab/BL602/CHIPPlatformConfig.h +++ b/src/platform/bouffalolab/BL602/CHIPPlatformConfig.h @@ -109,6 +109,10 @@ #define CHIP_CONFIG_MAX_LOCAL_ADDR_UDP_ENDPOINTS 4 #endif // CHIP_CONFIG_MAX_LOCAL_ADDR_UDP_ENDPOINTS +#ifndef CHIP_CONFIG_MAX_FABRICS +#define CHIP_CONFIG_MAX_FABRICS 6 // 5 fabrics + 1 for rotation slack +#endif + // ==================== Security Configuration Overrides ==================== #ifndef CHIP_CONFIG_DEBUG_CERT_VALIDATION diff --git a/src/platform/bouffalolab/BL602/ConfigurationManagerImpl.cpp b/src/platform/bouffalolab/BL602/ConfigurationManagerImpl.cpp index 463997cf0b29d7..f207e295ca882f 100644 --- a/src/platform/bouffalolab/BL602/ConfigurationManagerImpl.cpp +++ b/src/platform/bouffalolab/BL602/ConfigurationManagerImpl.cpp @@ -216,6 +216,7 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) CHIP_ERROR err; ChipLogProgress(DeviceLayer, "Performing factory reset"); + ef_env_set_default(); ChipLogProgress(DeviceLayer, "System restarting"); hal_reboot(); } diff --git a/src/platform/bouffalolab/BL602/DiagnosticDataProviderImpl.cpp b/src/platform/bouffalolab/BL602/DiagnosticDataProviderImpl.cpp index eedf4eebf056a5..f116522a12b0c2 100644 --- a/src/platform/bouffalolab/BL602/DiagnosticDataProviderImpl.cpp +++ b/src/platform/bouffalolab/BL602/DiagnosticDataProviderImpl.cpp @@ -163,11 +163,29 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(BootReasonType & bootReason return CHIP_NO_ERROR; } +static int bl_netif_get_all_ip6(struct netif * netif, ip6_addr_t if_ip6[]) +{ + if (netif == NULL || if_ip6 == NULL) + { + return 0; + } + + int addr_count = 0; + for (int i = 0; (i < LWIP_IPV6_NUM_ADDRESSES) && (i < kMaxIPv6AddrCount); i++) + { + if (!ip_addr_cmp(&netif->ip6_addr[i], IP6_ADDR_ANY)) + { + memcpy(&if_ip6[addr_count++], &netif->ip6_addr[i], sizeof(ip6_addr_t)); + } + } + + return addr_count; +} + CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** netifpp) { NetworkInterface * ifp = new NetworkInterface(); struct netif * netif; - uint8_t mac_addr[6]; netif = wifi_mgmr_sta_netif_get(); if (netif) @@ -179,10 +197,28 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetNetworkInterfaces(NetworkInterface ** ifp->type = EMBER_ZCL_INTERFACE_TYPE_WI_FI; ifp->offPremiseServicesReachableIPv4.SetNull(); ifp->offPremiseServicesReachableIPv6.SetNull(); - bl_efuse_read_mac(mac_addr); - memcpy(ifp->MacAddress, mac_addr, sizeof(mac_addr)); + bl_efuse_read_mac(ifp->MacAddress); + ifp->hardwareAddress = ByteSpan(ifp->MacAddress, 6); + + uint32_t ip, gw, mask; + wifi_mgmr_sta_ip_get(&ip, &gw, &mask); + memcpy(ifp->Ipv4AddressesBuffer[0], &ip, kMaxIPv4AddrSize); + ifp->Ipv4AddressSpans[0] = ByteSpan(ifp->Ipv4AddressesBuffer[0], kMaxIPv4AddrSize); + ifp->IPv4Addresses = chip::app::DataModel::List(ifp->Ipv4AddressSpans, 1); + + uint8_t ipv6_addr_count = 0; + ip6_addr_t ip6_addr[kMaxIPv6AddrCount]; + ipv6_addr_count = bl_netif_get_all_ip6(netif, ip6_addr); + for (uint8_t idx = 0; idx < ipv6_addr_count; ++idx) + { + memcpy(ifp->Ipv6AddressesBuffer[idx], ip6_addr[idx].addr, kMaxIPv6AddrSize); + ifp->Ipv6AddressSpans[idx] = ByteSpan(ifp->Ipv6AddressesBuffer[idx], kMaxIPv6AddrSize); + } + ifp->IPv6Addresses = chip::app::DataModel::List(ifp->Ipv6AddressSpans, ipv6_addr_count); } + *netifpp = ifp; + return CHIP_NO_ERROR; } @@ -256,8 +292,7 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiBeaconLostCount(uint32_t & beaconL CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiCurrentMaxRate(uint64_t & currentMaxRate) { - currentMaxRate = 0; - return CHIP_NO_ERROR; + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } CHIP_ERROR DiagnosticDataProviderImpl::GetWiFiPacketMulticastRxCount(uint32_t & packetMulticastRxCount) diff --git a/src/platform/bouffalolab/BL602/NetworkCommissioningDriver.cpp b/src/platform/bouffalolab/BL602/NetworkCommissioningDriver.cpp index 1a99e17b6b4dd9..b99b4d212ae739 100644 --- a/src/platform/bouffalolab/BL602/NetworkCommissioningDriver.cpp +++ b/src/platform/bouffalolab/BL602/NetworkCommissioningDriver.cpp @@ -32,6 +32,8 @@ #include #include +#define WIFI_STA_DISCONNECT_DELAY (pdMS_TO_TICKS(200)) + using namespace ::chip; //#if CHIP_DEVICE_CONFIG_ENABLE_WIFI namespace chip { @@ -121,6 +123,9 @@ bool BLWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) Status BLWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) { + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); @@ -136,6 +141,9 @@ Status BLWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, Mut Status BLWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) { + outDebugText.reduce_size(0); + outNetworkIndex = 0; + VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); // Use empty ssid for representing invalid network @@ -145,6 +153,8 @@ Status BLWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebu Status BLWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) { + outDebugText.reduce_size(0); + // Only one network is supported now VerifyOrReturnError(index == 0, Status::kOutOfRange); VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); @@ -157,12 +167,24 @@ CHIP_ERROR BLWiFiDriver::ConnectWiFiNetwork(const char * ssid, uint8_t ssidLen, char wifi_ssid[64] = { 0 }; char passwd[64] = { 0 }; - // Set the wifi configuration + int state = 0; + + wifi_mgmr_sta_disconnect(); + vTaskDelay(WIFI_STA_DISCONNECT_DELAY); + + wifi_mgmr_sta_disable(NULL); + wifi_mgmr_state_get(&state); + while (state != WIFI_STATE_IDLE) + { + wifi_mgmr_state_get(&state); + vTaskDelay(100); + } + memcpy(wifi_ssid, ssid, ssidLen); memcpy(passwd, key, keyLen); wifi_interface_t wifi_interface; wifi_interface = wifi_mgmr_sta_enable(); - wifi_mgmr_sta_connect(wifi_interface, ssid, passwd, NULL, NULL, 0, 0); + wifi_mgmr_sta_connect(wifi_interface, wifi_ssid, passwd, NULL, NULL, 0, 0); ReturnErrorOnFailure(ConnectivityMgr().SetWiFiStationMode(ConnectivityManager::kWiFiStationMode_Disabled)); @@ -280,6 +302,7 @@ void BLWiFiDriver::OnScanWiFiNetworkDone() } })) { + vPortFree(ScanResult); ChipLogProgress(DeviceLayer, "ScheduleLambda OK"); } } diff --git a/src/platform/bouffalolab/BL602/OTAImageProcessorImpl.cpp b/src/platform/bouffalolab/BL602/OTAImageProcessorImpl.cpp index 6a94570ac2abb5..a24d9316f6d5f7 100644 --- a/src/platform/bouffalolab/BL602/OTAImageProcessorImpl.cpp +++ b/src/platform/bouffalolab/BL602/OTAImageProcessorImpl.cpp @@ -158,7 +158,7 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) } DeviceLayer::SystemLayer().StartTimer( - System::Clock::Seconds32(2), + System::Clock::Seconds32(4), [](Layer *, void *) { ChipLogProgress(SoftwareUpdate, "Rebooting..."); hal_reboot(); diff --git a/src/platform/bouffalolab/BL602/PlatformManagerImpl.cpp b/src/platform/bouffalolab/BL602/PlatformManagerImpl.cpp index 7e0ad568cdbe78..930ff9cd292bdf 100644 --- a/src/platform/bouffalolab/BL602/PlatformManagerImpl.cpp +++ b/src/platform/bouffalolab/BL602/PlatformManagerImpl.cpp @@ -67,6 +67,8 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s static void WifiStaDisconect(void) { + NetworkCommissioning::BLWiFiDriver::GetInstance().SetLastDisconnectReason(NULL); + uint16_t reason = NetworkCommissioning::BLWiFiDriver::GetInstance().GetLastDisconnectReason(); uint8_t associationFailureCause = chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCause::kUnknown); @@ -138,7 +140,6 @@ static void WifiStaDisconect(void) chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::WiFiConnectionStatus::kNotConnected)); } - NetworkCommissioning::BLWiFiDriver::GetInstance().SetLastDisconnectReason(NULL); ConnectivityMgrImpl().ChangeWiFiStationState(ConnectivityManagerImpl::kWiFiStationState_Disconnecting); } diff --git a/third_party/bouffalolab/bl602/bl602_sdk.gni b/third_party/bouffalolab/bl602/bl602_sdk.gni index b2c14a30cafb01..ce3ca73a90a7c7 100644 --- a/third_party/bouffalolab/bl602/bl602_sdk.gni +++ b/third_party/bouffalolab/bl602/bl602_sdk.gni @@ -189,7 +189,7 @@ template("bl602_sdk") { "SYS_AOS_LOOP_ENABLE=1", "BL602_USE_HAL_DRIVER=1", "BL602=BL602", - "SYS_LOOPRT_ENABLE=1", + "CFG_TXDESC=2", "CFG_STA_MAX=1", "CFG_CHIP_BL602", @@ -295,11 +295,6 @@ template("bl602_sdk") { cflags_cc += [ "-std=c++17" ] cflags_cc += [ "-D _GNU_SOURCE" ] - #cflags_cc += [ "-fcommon" ] - #cflags_cc += [ "-fno-rtti" ] - #cflags_cc += [ "-Wnon-virtual-dtor" ] - #cflags_cc += [ "-frtti" ] - foreach(include_dir, _include_dirs) { cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ] } diff --git a/third_party/bouffalolab/repo b/third_party/bouffalolab/repo index 78561b2b5f72c3..880fc351904db2 160000 --- a/third_party/bouffalolab/repo +++ b/third_party/bouffalolab/repo @@ -1 +1 @@ -Subproject commit 78561b2b5f72c340afa94eb2be56fca7e6cab636 +Subproject commit 880fc351904db2825d3a2c767d60fe1ae8cc5722 From 786a01efa16cafc10fba07cfe7321264356d29f4 Mon Sep 17 00:00:00 2001 From: Jerry Johns Date: Fri, 16 Sep 2022 11:45:34 -0400 Subject: [PATCH 04/22] Omit write-only attributes in wildcard processing (#22686) * Omit write-only attributes in wildcard processing This omits processing write-only attributes during wildcard processing of Reads/Subscribes. It only achieves this for attributes backed by the AttributeAccessInterface. Specifically, it watches for UnsupportedRead error being returned by AttributeAccessInterface::Read and if so, ignores the error specifically when handling a wildcard-based interaction. Added a Python test that validates that the new WriteOnlyInt8u attribute is not served when doing a wildcard read. * Restyle --- .../all-clusters-app.matter | 2 + .../all-clusters-common/all-clusters-app.zap | 19 ++- .../test-cluster-server.cpp | 3 + .../util/ember-compatibility-functions.cpp | 9 ++ .../zcl/data-model/chip/test-cluster.xml | 2 + .../python/chip/clusters/Objects.py | 18 +++ .../test/test_scripts/cluster_objects.py | 9 ++ .../MTRAttributeTLVValueDecoder.mm | 11 ++ .../CHIP/zap-generated/MTRBaseClusters.h | 18 +++ .../CHIP/zap-generated/MTRBaseClusters.mm | 100 ++++++++++++++++ .../CHIP/zap-generated/MTRClusterConstants.h | 1 + .../CHIP/zap-generated/MTRClusters.h | 7 ++ .../CHIP/zap-generated/MTRClusters.mm | 27 +++++ .../zap-generated/endpoint_config.h | 20 ++-- .../app-common/zap-generated/attribute-id.h | 1 + .../zap-generated/attributes/Accessors.cpp | 31 +++++ .../zap-generated/attributes/Accessors.h | 5 + .../zap-generated/cluster-objects.cpp | 3 + .../zap-generated/cluster-objects.h | 13 ++ .../app-common/zap-generated/ids/Attributes.h | 4 + .../zap-generated/cluster/Commands.h | 7 +- .../cluster/logging/DataModelLogger.cpp | 5 + .../zap-generated/cluster/Commands.h | 111 ++++++++++++++++++ 23 files changed, 415 insertions(+), 11 deletions(-) diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 6ff3c099333d05..71da6771c0e97a 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -3708,6 +3708,7 @@ server cluster TestCluster = 4294048773 { attribute nullable int8s nullableRangeRestrictedInt8s = 16423; attribute nullable int16u nullableRangeRestrictedInt16u = 16424; attribute nullable int16s nullableRangeRestrictedInt16s = 16425; + attribute int8u writeOnlyInt8u = 16426; readonly attribute bitmap32 featureMap = 65532; readonly attribute int16u clusterRevision = 65533; @@ -4772,6 +4773,7 @@ endpoint 1 { ram attribute nullableRangeRestrictedInt8s default = -20; ram attribute nullableRangeRestrictedInt16u default = 200; ram attribute nullableRangeRestrictedInt16s default = -100; + callback attribute writeOnlyInt8u; ram attribute featureMap; ram attribute clusterRevision default = 1; } diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 08edd158a5ee99..daca44d7b782ee 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -20700,6 +20700,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "write_only_int8u", + "code": 16426, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "AttributeList", "code": 65531, @@ -24724,5 +24740,6 @@ "endpointVersion": 1, "deviceIdentifier": 61442 } - ] + ], + "log": [] } \ No newline at end of file diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index 0da23b39b189e1..8647c7be0b12e4 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -170,6 +170,9 @@ CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attribu case ClusterErrorBoolean::Id: { return StatusIB(Protocols::InteractionModel::Status::Failure, 17).ToChipError(); } + case WriteOnlyInt8u::Id: { + return StatusIB(Protocols::InteractionModel::Status::UnsupportedRead).ToChipError(); + } default: { break; } diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 3ac3b3258c41bc..31390a973ad4e3 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -475,6 +475,15 @@ CHIP_ERROR ReadViaAccessInterface(FabricIndex aAccessingFabricIndex, bool aIsFab AttributeValueEncoder valueEncoder(aAttributeReports, aAccessingFabricIndex, aPath, version, aIsFabricFiltered, state); CHIP_ERROR err = aAccessInterface->Read(aPath, valueEncoder); + if (err == CHIP_IM_GLOBAL_STATUS(UnsupportedRead) && aPath.mExpanded) + { + // + // Set this to true to ensure our caller will return immediately without proceeding further. + // + *aTriedEncode = true; + return CHIP_NO_ERROR; + } + if (err != CHIP_NO_ERROR) { // If the err is not CHIP_NO_ERROR, means the encoding was aborted, then the valueEncoder may save its state. diff --git a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml index ba5db80d1708ef..da8acf50bbd389 100644 --- a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml @@ -232,6 +232,8 @@ limitations under the License. nullable_range_restricted_int16u nullable_range_restricted_int16s + write_only_int8u + unsupported diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 49ea204a2ecb34..69e82312c9aa1a 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -26685,6 +26685,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="nullableRangeRestrictedInt8s", Tag=0x00004027, Type=typing.Union[Nullable, int]), ClusterObjectFieldDescriptor(Label="nullableRangeRestrictedInt16u", Tag=0x00004028, Type=typing.Union[Nullable, uint]), ClusterObjectFieldDescriptor(Label="nullableRangeRestrictedInt16s", Tag=0x00004029, Type=typing.Union[Nullable, int]), + ClusterObjectFieldDescriptor(Label="writeOnlyInt8u", Tag=0x0000402A, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="attributeList", Tag=0x0000FFFB, Type=typing.List[uint]), @@ -26773,6 +26774,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: nullableRangeRestrictedInt8s: 'typing.Union[Nullable, int]' = None nullableRangeRestrictedInt16u: 'typing.Union[Nullable, uint]' = None nullableRangeRestrictedInt16s: 'typing.Union[Nullable, int]' = None + writeOnlyInt8u: 'typing.Optional[uint]' = None generatedCommandList: 'typing.List[uint]' = None acceptedCommandList: 'typing.List[uint]' = None attributeList: 'typing.List[uint]' = None @@ -28854,6 +28856,22 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'typing.Union[Nullable, int]' = NullValue + @dataclass + class WriteOnlyInt8u(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0xFFF1FC05 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x0000402A + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.Optional[uint]) + + value: 'typing.Optional[uint]' = None + @dataclass class GeneratedCommandList(ClusterAttributeDescriptor): @ChipUtility.classproperty diff --git a/src/controller/python/test/test_scripts/cluster_objects.py b/src/controller/python/test/test_scripts/cluster_objects.py index 5a9db3dd6ba28c..896d0c79103421 100644 --- a/src/controller/python/test/test_scripts/cluster_objects.py +++ b/src/controller/python/test/test_scripts/cluster_objects.py @@ -122,6 +122,14 @@ async def TestCommandWithResponse(cls, devCtrl): if res.returnValue != 5: raise ValueError() + @classmethod + @base.test_case + async def TestReadWriteOnlyAttribute(cls, devCtrl): + logger.info("Test wildcard read of attributes containing write-only attribute") + res = await devCtrl.ReadAttribute(nodeid=NODE_ID, attributes=[(Clusters.TestCluster)]) + if Clusters.TestCluster.Attributes.WriteOnlyInt8u in res[1][Clusters.TestCluster]: + raise AssertionError("Received un-expected WriteOnlyInt8u attribute in TestCluster") + @classmethod @base.test_case async def TestWriteRequest(cls, devCtrl): @@ -560,6 +568,7 @@ def eventPathPossibilities(): async def RunTest(cls, devCtrl): try: cls.TestAPI() + await cls.TestReadWriteOnlyAttribute(devCtrl) await cls.TestCommandRoundTrip(devCtrl) await cls.TestCommandRoundTripWithBadEndpoint(devCtrl) await cls.TestCommandWithResponse(devCtrl) diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index a64e8844bf90ff..d49aab980c3ebe 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -17449,6 +17449,17 @@ id MTRDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::TLVReader & } return value; } + case Attributes::WriteOnlyInt8u::Id: { + using TypeInfo = Attributes::WriteOnlyInt8u::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedChar:cppValue]; + return value; + } case Attributes::GeneratedCommandList::Id: { using TypeInfo = Attributes::GeneratedCommandList::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 68d99cab53237f..2e6fc6dd0a061e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -19017,6 +19017,24 @@ labels. completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion; +- (void)readAttributeWriteOnlyInt8uWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion; +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion; +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSNumber * _Nonnull)value + params:(MTRWriteParams * _Nullable)params + completion:(MTRStatusCompletion)completion; +/** + * This API does not support setting autoResubscribe to NO in the + * MTRSubscribeParams. + */ +- (void)subscribeAttributeWriteOnlyInt8uWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; ++ (void)readAttributeWriteOnlyInt8uWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer + endpoint:(NSNumber *)endpoint + queue:(dispatch_queue_t)queue + completion: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion; + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion; /** * This API does not support setting autoResubscribe to NO in the diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index b03296b6272417..ca61f4e073a805 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -85853,6 +85853,106 @@ new MTRNullableInt16sAttributeCallbackBridge(queue, completion, ^(Cancelable * s }); } +- (void)readAttributeWriteOnlyInt8uWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + new MTRInt8uAttributeCallbackBridge(self.callbackQueue, self.device, completion, + ^(ExchangeManager & exchangeManager, const SessionHandle & session, Cancelable * success, Cancelable * failure) { + using TypeInfo = TestCluster::Attributes::WriteOnlyInt8u::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + chip::Controller::TestClusterCluster cppCluster(exchangeManager, session, self->_endpoint); + return cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSNumber * _Nonnull)value completion:(MTRStatusCompletion)completion +{ + [self writeAttributeWriteOnlyInt8uWithValue:(NSNumber * _Nonnull) value params:nil completion:completion]; +} +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSNumber * _Nonnull)value + params:(MTRWriteParams * _Nullable)params + completion:(MTRStatusCompletion)completion +{ + // Make a copy of params before we go async. + params = [params copy]; + value = [value copy]; + + new MTRDefaultSuccessCallbackBridge( + self.callbackQueue, self.device, + ^(id _Nullable ignored, NSError * _Nullable error) { + completion(error); + }, + ^(ExchangeManager & exchangeManager, const SessionHandle & session, Cancelable * success, Cancelable * failure) { + chip::Optional timedWriteTimeout; + if (params != nil) { + if (params.timedWriteTimeout != nil) { + timedWriteTimeout.SetValue(params.timedWriteTimeout.unsignedShortValue); + } + } + + ListFreer listFreer; + using TypeInfo = TestCluster::Attributes::WriteOnlyInt8u::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.unsignedCharValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + + chip::Controller::TestClusterCluster cppCluster(exchangeManager, session, self->_endpoint); + return cppCluster.WriteAttribute( + cppValue, successFn->mContext, successFn->mCall, failureFn->mCall, timedWriteTimeout); + }); +} + +- (void)subscribeAttributeWriteOnlyInt8uWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + // Make a copy of params before we go async. + params = [params copy]; + new MTRInt8uAttributeCallbackSubscriptionBridge( + self.callbackQueue, self.device, reportHandler, + ^(ExchangeManager & exchangeManager, const SessionHandle & session, Cancelable * success, Cancelable * failure) { + if (!params.autoResubscribe) { + // We don't support disabling auto-resubscribe. + return CHIP_ERROR_INVALID_ARGUMENT; + } + using TypeInfo = TestCluster::Attributes::WriteOnlyInt8u::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + + chip::Controller::TestClusterCluster cppCluster(exchangeManager, session, self->_endpoint); + return cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + [params.minInterval unsignedShortValue], [params.maxInterval unsignedShortValue], + MTRInt8uAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished, nil, params.fabricFiltered, + params.keepPreviousSubscriptions); + }, + subscriptionEstablished); +} + ++ (void)readAttributeWriteOnlyInt8uWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer + endpoint:(NSNumber *)endpoint + queue:(dispatch_queue_t)queue + completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + new MTRInt8uAttributeCallbackBridge(queue, completion, ^(Cancelable * success, Cancelable * failure) { + if (clusterStateCacheContainer.cppClusterStateCache) { + chip::app::ConcreteAttributePath path; + using TypeInfo = TestCluster::Attributes::WriteOnlyInt8u::TypeInfo; + path.mEndpointId = static_cast([endpoint unsignedShortValue]); + path.mClusterId = TypeInfo::GetClusterId(); + path.mAttributeId = TypeInfo::GetAttributeId(); + TypeInfo::DecodableType value; + CHIP_ERROR err = clusterStateCacheContainer.cppClusterStateCache->Get(path, value); + auto successFn = Callback::FromCancelable(success); + if (err == CHIP_NO_ERROR) { + successFn->mCall(successFn->mContext, value); + } + return err; + } + return CHIP_ERROR_NOT_FOUND; + }); +} + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { new MTRTestClusterGeneratedCommandListListAttributeCallbackBridge(self.callbackQueue, self.device, completion, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 4318c4fa50e459..2df9246dc8a98b 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -1445,6 +1445,7 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterTestClusterAttributeNullableRangeRestrictedInt8sID = 0x00004027, MTRAttributeIDTypeClusterTestClusterAttributeNullableRangeRestrictedInt16uID = 0x00004028, MTRAttributeIDTypeClusterTestClusterAttributeNullableRangeRestrictedInt16sID = 0x00004029, + MTRAttributeIDTypeClusterTestClusterAttributeWriteOnlyInt8uID = 0x0000402A, MTRAttributeIDTypeClusterTestClusterAttributeGeneratedCommandListID = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterTestClusterAttributeAcceptedCommandListID = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterTestClusterAttributeAttributeListID = MTRAttributeIDTypeGlobalAttributeAttributeListID, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index 32ca6ee39e5e48..2182161a4f13ac 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -5301,6 +5301,13 @@ labels. expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params; +- (NSDictionary *)readAttributeWriteOnlyInt8uWithParams:(MTRReadParams * _Nullable)params; +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSDictionary *)dataValueDictionary + expectedValueInterval:(NSNumber *)expectedValueIntervalMs; +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSDictionary *)dataValueDictionary + expectedValueInterval:(NSNumber *)expectedValueIntervalMs + params:(MTRWriteParams * _Nullable)params; + - (NSDictionary *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params; - (NSDictionary *)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 66ec9e6d9fe890..98f95c8899f820 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -22304,6 +22304,33 @@ - (void)writeAttributeNullableRangeRestrictedInt16sWithValue:(NSDictionary *)readAttributeWriteOnlyInt8uWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:@(_endpoint) + clusterID:@(MTRClusterIDTypeTestClusterID) + attributeID:@(MTRAttributeIDTypeClusterTestClusterAttributeWriteOnlyInt8uID) + params:params]; +} + +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSDictionary *)dataValueDictionary + expectedValueInterval:(NSNumber *)expectedValueIntervalMs +{ + [self writeAttributeWriteOnlyInt8uWithValue:dataValueDictionary expectedValueInterval:expectedValueIntervalMs params:nil]; +} +- (void)writeAttributeWriteOnlyInt8uWithValue:(NSDictionary *)dataValueDictionary + expectedValueInterval:(NSNumber *)expectedValueIntervalMs + params:(MTRWriteParams * _Nullable)params +{ + NSNumber * timedWriteTimeout = params.timedWriteTimeout; + + [self.device writeAttributeWithEndpointID:@(_endpoint) + clusterID:@(MTRClusterIDTypeTestClusterID) + attributeID:@(MTRAttributeIDTypeClusterTestClusterAttributeWriteOnlyInt8uID) + value:dataValueDictionary + expectedValueInterval:expectedValueIntervalMs + timedWriteTimeout:timedWriteTimeout]; +} + - (NSDictionary *)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:@(_endpoint) diff --git a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h index d2167954be34cd..31bf827df73545 100644 --- a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h +++ b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h @@ -369,7 +369,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 717 +#define GENERATED_ATTRIBUTE_COUNT 718 #define GENERATED_ATTRIBUTES \ { \ \ @@ -1429,7 +1429,9 @@ ZAP_MIN_MAX_DEFAULTS_INDEX(44) }, /* nullable_range_restricted_int16u */ \ { 0x00004029, ZAP_TYPE(INT16S), 2, \ ZAP_ATTRIBUTE_MASK(MIN_MAX) | ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ - ZAP_MIN_MAX_DEFAULTS_INDEX(45) }, /* nullable_range_restricted_int16s */ \ + ZAP_MIN_MAX_DEFAULTS_INDEX(45) }, /* nullable_range_restricted_int16s */ \ + { 0x0000402A, ZAP_TYPE(INT8U), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* write_only_int8u */ \ { 0x0000FFFC, ZAP_TYPE(BITMAP32), 4, 0, ZAP_SIMPLE_DEFAULT(0) }, /* FeatureMap */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(1) }, /* ClusterRevision */ \ \ @@ -2691,7 +2693,7 @@ /* Endpoint: 1, Cluster: Test Cluster (server) */ \ .clusterId = 0xFFF1FC05, \ .attributes = ZAP_ATTRIBUTE_INDEX(596), \ - .attributeCount = 82, \ + .attributeCount = 83, \ .clusterSize = 2289, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ .functions = NULL, \ @@ -2701,7 +2703,7 @@ { \ /* Endpoint: 2, Cluster: Groups (server) */ \ .clusterId = 0x00000004, \ - .attributes = ZAP_ATTRIBUTE_INDEX(678), \ + .attributes = ZAP_ATTRIBUTE_INDEX(679), \ .attributeCount = 3, \ .clusterSize = 7, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2712,7 +2714,7 @@ { \ /* Endpoint: 2, Cluster: On/Off (server) */ \ .clusterId = 0x00000006, \ - .attributes = ZAP_ATTRIBUTE_INDEX(681), \ + .attributes = ZAP_ATTRIBUTE_INDEX(682), \ .attributeCount = 7, \ .clusterSize = 13, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2723,7 +2725,7 @@ { \ /* Endpoint: 2, Cluster: Descriptor (server) */ \ .clusterId = 0x0000001D, \ - .attributes = ZAP_ATTRIBUTE_INDEX(688), \ + .attributes = ZAP_ATTRIBUTE_INDEX(689), \ .attributeCount = 6, \ .clusterSize = 4, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -2734,7 +2736,7 @@ { \ /* Endpoint: 2, Cluster: Power Source (server) */ \ .clusterId = 0x0000002F, \ - .attributes = ZAP_ATTRIBUTE_INDEX(694), \ + .attributes = ZAP_ATTRIBUTE_INDEX(695), \ .attributeCount = 8, \ .clusterSize = 72, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ @@ -2745,7 +2747,7 @@ { \ /* Endpoint: 2, Cluster: Occupancy Sensing (server) */ \ .clusterId = 0x00000406, \ - .attributes = ZAP_ATTRIBUTE_INDEX(702), \ + .attributes = ZAP_ATTRIBUTE_INDEX(703), \ .attributeCount = 5, \ .clusterSize = 9, \ .mask = ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2756,7 +2758,7 @@ { \ /* Endpoint: 65534, Cluster: Network Commissioning (server) */ \ .clusterId = 0x00000031, \ - .attributes = ZAP_ATTRIBUTE_INDEX(707), \ + .attributes = ZAP_ATTRIBUTE_INDEX(708), \ .attributeCount = 10, \ .clusterSize = 0, \ .mask = ZAP_CLUSTER_MASK(SERVER), \ diff --git a/zzz_generated/app-common/app-common/zap-generated/attribute-id.h b/zzz_generated/app-common/app-common/zap-generated/attribute-id.h index ab7abb68c6bc5c..8872d8decf56dd 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attribute-id.h +++ b/zzz_generated/app-common/app-common/zap-generated/attribute-id.h @@ -1219,6 +1219,7 @@ #define ZCL_NULLABLE_RANGE_RESTRICTED_INT8S_ATTRIBUTE_ID (0x4027) #define ZCL_NULLABLE_RANGE_RESTRICTED_INT16_U_ATTRIBUTE_ID (0x4028) #define ZCL_NULLABLE_RANGE_RESTRICTED_INT16_S_ATTRIBUTE_ID (0x4029) +#define ZCL_WRITE_ONLY_INT8_U_ATTRIBUTE_ID (0x402A) // Attribute ids for cluster: Fault Injection diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index 4cba25b122d69c..ec5fc6f0b6d990 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -30692,6 +30692,37 @@ EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullabl } // namespace NullableRangeRestrictedInt16s +namespace WriteOnlyInt8u { + +EmberAfStatus Get(chip::EndpointId endpoint, uint8_t * value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + EmberAfStatus status = emberAfReadServerAttribute(endpoint, Clusters::TestCluster::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); + if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + *value = Traits::StorageToWorking(temp); + return status; +} +EmberAfStatus Set(chip::EndpointId endpoint, uint8_t value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteServerAttribute(endpoint, Clusters::TestCluster::Id, Id, writable, ZCL_INT8U_ATTRIBUTE_TYPE); +} + +} // namespace WriteOnlyInt8u + namespace FeatureMap { EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index f4d9c7fea31405..c7543c2a5c9ff7 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -5097,6 +5097,11 @@ EmberAfStatus SetNull(chip::EndpointId endpoint); EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value); } // namespace NullableRangeRestrictedInt16s +namespace WriteOnlyInt8u { +EmberAfStatus Get(chip::EndpointId endpoint, uint8_t * value); // int8u +EmberAfStatus Set(chip::EndpointId endpoint, uint8_t value); +} // namespace WriteOnlyInt8u + namespace FeatureMap { EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32 EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value); diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index c3e83283443daf..c265db1a4443fe 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -20762,6 +20762,9 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre case Attributes::NullableRangeRestrictedInt16s::TypeInfo::GetAttributeId(): ReturnErrorOnFailure(DataModel::Decode(reader, nullableRangeRestrictedInt16s)); break; + case Attributes::WriteOnlyInt8u::TypeInfo::GetAttributeId(): + ReturnErrorOnFailure(DataModel::Decode(reader, writeOnlyInt8u)); + break; case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): ReturnErrorOnFailure(DataModel::Decode(reader, generatedCommandList)); break; diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 538709b05c8c09..38aa0198ee1a22 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -27868,6 +27868,18 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return false; } }; } // namespace NullableRangeRestrictedInt16s +namespace WriteOnlyInt8u { +struct TypeInfo +{ + using Type = uint8_t; + using DecodableType = uint8_t; + using DecodableArgType = uint8_t; + + static constexpr ClusterId GetClusterId() { return Clusters::TestCluster::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::WriteOnlyInt8u::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace WriteOnlyInt8u namespace GeneratedCommandList { struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo { @@ -27992,6 +28004,7 @@ struct TypeInfo Attributes::NullableRangeRestrictedInt8s::TypeInfo::DecodableType nullableRangeRestrictedInt8s; Attributes::NullableRangeRestrictedInt16u::TypeInfo::DecodableType nullableRangeRestrictedInt16u; Attributes::NullableRangeRestrictedInt16s::TypeInfo::DecodableType nullableRangeRestrictedInt16s; + Attributes::WriteOnlyInt8u::TypeInfo::DecodableType writeOnlyInt8u = static_cast(0); Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; Attributes::AttributeList::TypeInfo::DecodableType attributeList; diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index 4ad8017f1f1101..d61a60453231ba 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -4932,6 +4932,10 @@ namespace NullableRangeRestrictedInt16s { static constexpr AttributeId Id = 0x00004029; } // namespace NullableRangeRestrictedInt16s +namespace WriteOnlyInt8u { +static constexpr AttributeId Id = 0x0000402A; +} // namespace WriteOnlyInt8u + namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; } // namespace GeneratedCommandList diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 9994795a0ed905..40b1760e02ba07 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -7405,6 +7405,7 @@ class ElectricalMeasurementGetMeasurementProfileCommand : public ClusterCommand | * NullableRangeRestrictedInt8s | 0x4027 | | * NullableRangeRestrictedInt16u | 0x4028 | | * NullableRangeRestrictedInt16s | 0x4029 | +| * WriteOnlyInt8u | 0x402A | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * AttributeList | 0xFFFB | @@ -13034,6 +13035,7 @@ void registerClusterTestCluster(Commands & commands, CredentialIssuerCommands * credsIssuerConfig), // make_unique(Id, "nullable-range-restricted-int16s", Attributes::NullableRangeRestrictedInt16s::Id, credsIssuerConfig), // + make_unique(Id, "write-only-int8u", Attributes::WriteOnlyInt8u::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // @@ -13189,7 +13191,9 @@ void registerClusterTestCluster(Commands & commands, CredentialIssuerCommands * credsIssuerConfig), // make_unique>>( Id, "nullable-range-restricted-int16s", INT16_MIN, INT16_MAX, Attributes::NullableRangeRestrictedInt16s::Id, - credsIssuerConfig), // + credsIssuerConfig), // + make_unique>(Id, "write-only-int8u", 0, UINT8_MAX, Attributes::WriteOnlyInt8u::Id, + credsIssuerConfig), // make_unique(Id, credsIssuerConfig), // make_unique(Id, "boolean", Attributes::Boolean::Id, credsIssuerConfig), // make_unique(Id, "bitmap8", Attributes::Bitmap8::Id, credsIssuerConfig), // @@ -13278,6 +13282,7 @@ void registerClusterTestCluster(Commands & commands, CredentialIssuerCommands * credsIssuerConfig), // make_unique(Id, "nullable-range-restricted-int16s", Attributes::NullableRangeRestrictedInt16s::Id, credsIssuerConfig), // + make_unique(Id, "write-only-int8u", Attributes::WriteOnlyInt8u::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index d4ac2c0dac24d2..05a186b290df5b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -9974,6 +9974,11 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("nullable_range_restricted_int16s", 1, value); } + case TestCluster::Attributes::WriteOnlyInt8u::Id: { + uint8_t value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("write_only_int8u", 1, value); + } case TestCluster::Attributes::GeneratedCommandList::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index cc9a85648ea956..b9dd1e684a1676 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -82544,6 +82544,7 @@ class SubscribeAttributeElectricalMeasurementClusterRevision : public SubscribeA | * NullableRangeRestrictedInt8s | 0x4027 | | * NullableRangeRestrictedInt16u | 0x4028 | | * NullableRangeRestrictedInt16s | 0x4029 | +| * WriteOnlyInt8u | 0x402A | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * AttributeList | 0xFFFB | @@ -93110,6 +93111,113 @@ class SubscribeAttributeTestClusterNullableRangeRestrictedInt16s : public Subscr } }; +/* + * Attribute WriteOnlyInt8u + */ +class ReadTestClusterWriteOnlyInt8u : public ReadAttribute { +public: + ReadTestClusterWriteOnlyInt8u() + : ReadAttribute("write-only-int8u") + { + } + + ~ReadTestClusterWriteOnlyInt8u() {} + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000402A) on endpoint %u", endpointId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device + endpoint:@(endpointId) + queue:callbackQueue]; + [cluster readAttributeWriteOnlyInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"TestCluster.WriteOnlyInt8u response %@", [value description]); + if (error != nil) { + LogNSError("TestCluster WriteOnlyInt8u read Error", error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class WriteTestClusterWriteOnlyInt8u : public WriteAttribute { +public: + WriteTestClusterWriteOnlyInt8u() + : WriteAttribute("write-only-int8u") + { + AddArgument("attr-name", "write-only-int8u"); + AddArgument("attr-value", 0, UINT8_MAX, &mValue); + WriteAttribute::AddArguments(); + } + + ~WriteTestClusterWriteOnlyInt8u() {} + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000402A) on endpoint %u", endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device + endpoint:@(endpointId) + queue:callbackQueue]; + __auto_type * params = [[MTRWriteParams alloc] init]; + params.timedWriteTimeout + = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; + params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil; + NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue]; + + [cluster writeAttributeWriteOnlyInt8uWithValue:value + params:params + completion:^(NSError * _Nullable error) { + if (error != nil) { + LogNSError("TestCluster WriteOnlyInt8u write Error", error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } + +private: + uint8_t mValue; +}; + +class SubscribeAttributeTestClusterWriteOnlyInt8u : public SubscribeAttribute { +public: + SubscribeAttributeTestClusterWriteOnlyInt8u() + : SubscribeAttribute("write-only-int8u") + { + } + + ~SubscribeAttributeTestClusterWriteOnlyInt8u() {} + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000402A) on endpoint %u", endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device + endpoint:@(endpointId) + queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.keepPreviousSubscriptions = mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.fabricFiltered = mFabricFiltered.Value(); + } + [cluster subscribeAttributeWriteOnlyInt8uWithParams:params + subscriptionEstablished:^() { + mSubscriptionEstablished = YES; + } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"TestCluster.WriteOnlyInt8u response %@", [value description]); + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + /* * Attribute GeneratedCommandList */ @@ -96991,6 +97099,9 @@ void registerClusterTestCluster(Commands & commands) make_unique(), // make_unique(), // make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // make_unique(), // make_unique(), // make_unique(), // From ee897f1c17304c6e3936f04d73e956e16bd1005d Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Fri, 16 Sep 2022 08:48:11 -0700 Subject: [PATCH 05/22] add isFabricFiltered and keepSubscriptions flag (#22575) --- .../clusterclient/WildcardFragment.kt | 82 +++++---- .../app/src/main/res/layout/read_dialog.xml | 35 ++++ .../src/main/res/layout/subscribe_dialog.xml | 24 +++ .../src/main/res/layout/wildcard_fragment.xml | 1 + .../app/src/main/res/values/strings.xml | 6 + src/controller/java/AndroidCallbacks-JNI.cpp | 7 +- src/controller/java/AndroidCallbacks.cpp | 174 +++++++++++++++--- src/controller/java/AndroidCallbacks.h | 15 +- .../java/CHIPDeviceController-JNI.cpp | 109 ++--------- .../ChipDeviceController.java | 106 ++++++----- .../chip/devicecontroller/ReportCallback.java | 3 +- .../devicecontroller/ReportCallbackJni.java | 11 +- 12 files changed, 374 insertions(+), 199 deletions(-) create mode 100644 src/android/CHIPTool/app/src/main/res/layout/read_dialog.xml diff --git a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt index d93d56496fc904..9a29d0d598d549 100644 --- a/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt +++ b/src/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/WildcardFragment.kt @@ -44,26 +44,15 @@ class WildcardFragment : Fragment() { private lateinit var addressUpdateFragment: AddressUpdateFragment private val reportCallback = object : ReportCallback { - override fun onError(attributePath: ChipAttributePath, ex: Exception) { - Log.e(TAG, "Report error for $attributePath: $ex") - } - - override fun onReport(nodeState: NodeState) { - Log.i(TAG, "Received wildcard report") - - val debugString = nodeStateToDebugString(nodeState) - Log.i(TAG, debugString) - requireActivity().runOnUiThread { outputTv.text = debugString } - } - - override fun onDone() { - Log.i(TAG, "wildcard report Done") - } - } - - private val reportEventCallback = object : ReportEventCallback { - override fun onError(eventPath: ChipEventPath, ex: Exception) { - Log.e(TAG, "Report error for $eventPath: $ex") + override fun onError(attributePath: ChipAttributePath, eventPath: ChipEventPath, ex: Exception) { + if (attributePath != null) + { + Log.e(TAG, "Report error for $attributePath: $ex") + } + if (eventPath != null) + { + Log.e(TAG, "Report error for $eventPath: $ex") + } } override fun onReport(nodeState: NodeState) { @@ -87,9 +76,9 @@ class WildcardFragment : Fragment() { scope = viewLifecycleOwner.lifecycleScope return inflater.inflate(R.layout.wildcard_fragment, container, false).apply { subscribeBtn.setOnClickListener { scope.launch { showSubscribeDialog(ATTRIBUTE) } } - readBtn.setOnClickListener { scope.launch { read(ATTRIBUTE) } } + readBtn.setOnClickListener { scope.launch { showReadDialog(ATTRIBUTE) } } subscribeEventBtn.setOnClickListener { scope.launch { showSubscribeDialog(EVENT) } } - readEventBtn.setOnClickListener { scope.launch { read(EVENT) } } + readEventBtn.setOnClickListener { scope.launch { showReadDialog(EVENT) } } addressUpdateFragment = childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment @@ -121,7 +110,7 @@ class WildcardFragment : Fragment() { return stringBuilder.toString() } - private suspend fun subscribe(type: Int, minInterval: Int, maxInterval: Int) { + private suspend fun subscribe(type: Int, minInterval: Int, maxInterval: Int, keepSubscriptions: Boolean, isFabricFiltered: Boolean) { val subscriptionEstablishedCallback = SubscriptionEstablishedCallback { Log.i(TAG, "Subscription to device established") } @@ -137,26 +126,33 @@ class WildcardFragment : Fragment() { if (type == ATTRIBUTE) { val attributePath = ChipAttributePath.newInstance(endpointId, clusterId, attributeId) deviceController.subscribeToPath(subscriptionEstablishedCallback, + resubscriptionAttemptCallback, reportCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), listOf(attributePath), + null, minInterval, - maxInterval) + maxInterval, + keepSubscriptions, + isFabricFiltered) } else if (type == EVENT) { val eventPath = ChipEventPath.newInstance(endpointId, clusterId, eventId) - deviceController.subscribeToEventPath(subscriptionEstablishedCallback, + deviceController.subscribeToPath(subscriptionEstablishedCallback, resubscriptionAttemptCallback, - reportEventCallback, + reportCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), + null, listOf(eventPath), minInterval, - maxInterval) + maxInterval, + keepSubscriptions, + isFabricFiltered) } } - private suspend fun read(type: Int) { + private suspend fun read(type: Int, isFabricFiltered: Boolean) { val endpointId = getChipPathIdForText(endpointIdEd.text.toString()) val clusterId = getChipPathIdForText(clusterIdEd.text.toString()) val attributeId = getChipPathIdForText(attributeIdEd.text.toString()) @@ -167,16 +163,36 @@ class WildcardFragment : Fragment() { deviceController.readPath(reportCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - listOf(attributePath)) + listOf(attributePath), + null, + isFabricFiltered) } else if (type == EVENT) { val eventPath = ChipEventPath.newInstance(endpointId, clusterId, eventId) - deviceController.readEventPath(reportEventCallback, + deviceController.readPath(reportCallback, ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId), - listOf(eventPath)) + null, + listOf(eventPath), + isFabricFiltered) } } + private fun showReadDialog(type: Int) { + val dialogView = requireActivity().layoutInflater.inflate(R.layout.read_dialog, null) + val dialog = AlertDialog.Builder(requireContext()).apply { + setView(dialogView) + }.create() + + val isFabricFilteredEd = dialogView.findViewById(R.id.isFabricFilteredEd) + dialogView.findViewById