From ca747595beeee74a31f3c58238098f387e8a2f14 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 20 Oct 2022 21:06:21 +0800 Subject: [PATCH] esp_matter: Add support for nullable attribute setting and getting --- .../esp_matter/esp_matter_attribute.cpp | 309 +++-- components/esp_matter/esp_matter_attribute.h | 92 +- .../esp_matter/esp_matter_attribute_utils.cpp | 1103 ++++++++++++++--- .../esp_matter/esp_matter_attribute_utils.h | 125 +- components/esp_matter/esp_matter_cluster.cpp | 36 +- components/esp_matter/esp_matter_cluster.h | 26 +- components/esp_matter/esp_matter_feature.h | 12 +- 7 files changed, 1291 insertions(+), 412 deletions(-) diff --git a/components/esp_matter/esp_matter_attribute.cpp b/components/esp_matter/esp_matter_attribute.cpp index d0933d4de..052378197 100644 --- a/components/esp_matter/esp_matter_attribute.cpp +++ b/components/esp_matter/esp_matter_attribute.cpp @@ -237,7 +237,8 @@ namespace attribute { attribute_t *create_binding(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) { - return esp_matter::attribute::create(cluster, Binding::Attributes::Binding::Id, ATTRIBUTE_FLAG_WRITABLE, + return esp_matter::attribute::create(cluster, Binding::Attributes::Binding::Id, + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_array(value, length, count)); } @@ -250,7 +251,8 @@ namespace attribute { attribute_t *create_default_ota_providers(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) { return esp_matter::attribute::create(cluster, OtaSoftwareUpdateRequestor::Attributes::DefaultOtaProviders::Id, - ATTRIBUTE_FLAG_WRITABLE, esp_matter_array(value, length, count)); + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE, + esp_matter_array(value, length, count)); } attribute_t *create_update_possible(cluster_t *cluster, bool value) @@ -265,10 +267,10 @@ attribute_t *create_update_state(cluster_t *cluster, uint8_t value) ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); } -attribute_t *create_update_state_progress(cluster_t *cluster, uint8_t value) +attribute_t *create_update_state_progress(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, OtaSoftwareUpdateRequestor::Attributes::UpdateStateProgress::Id, - ATTRIBUTE_FLAG_NULLABLE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } } /* attribute */ @@ -343,10 +345,10 @@ attribute_t *create_interface_enabled(cluster_t *cluster, bool value) ATTRIBUTE_FLAG_WRITABLE, esp_matter_bool(value)); } -attribute_t *create_last_networking_status(cluster_t *cluster, uint8_t value) +attribute_t *create_last_networking_status(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, NetworkCommissioning::Attributes::LastNetworkingStatus::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } attribute_t *create_last_network_id(cluster_t *cluster, uint8_t *value, uint16_t length) @@ -355,10 +357,10 @@ attribute_t *create_last_network_id(cluster_t *cluster, uint8_t *value, uint16_t ATTRIBUTE_FLAG_NONE, esp_matter_octet_str(value, length)); } -attribute_t *create_last_connect_error_value(cluster_t *cluster, uint32_t value) +attribute_t *create_last_connect_error_value(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, NetworkCommissioning::Attributes::LastConnectErrorValue::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int32(value)); } } /* attribute */ @@ -493,76 +495,76 @@ attribute_t *create_bssid(cluster_t *cluster, uint8_t *value, uint16_t length) esp_matter_octet_str(value, length)); } -attribute_t *create_security_type(cluster_t *cluster, uint8_t value) +attribute_t *create_security_type(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::SecurityType::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_enum8(value)); } -attribute_t *create_wifi_version(cluster_t *cluster, uint8_t value) +attribute_t *create_wifi_version(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::WiFiVersion::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } -attribute_t *create_channel_number(cluster_t *cluster, uint16_t value) +attribute_t *create_channel_number(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::ChannelNumber::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint16(value)); } -attribute_t *create_rssi(cluster_t *cluster, int8_t value) +attribute_t *create_rssi(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::Rssi::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_int8(value)); + return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::Rssi::Id, ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_int8(value)); } -attribute_t *create_beacon_lost_count(cluster_t *cluster, uint32_t value) +attribute_t *create_beacon_lost_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::BeaconLostCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_beacon_rx_count(cluster_t *cluster, uint32_t value) +attribute_t *create_beacon_rx_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::BeaconRxCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_packet_multicast_rx_count(cluster_t *cluster, uint32_t value) +attribute_t *create_packet_multicast_rx_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::PacketMulticastRxCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_packet_multicast_tx_count(cluster_t *cluster, uint32_t value) +attribute_t *create_packet_multicast_tx_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::PacketMulticastTxCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_packet_unicast_rx_count(cluster_t *cluster, uint32_t value) +attribute_t *create_packet_unicast_rx_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::PacketUnicastRxCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_packet_unicast_tx_count(cluster_t *cluster, uint32_t value) +attribute_t *create_packet_unicast_tx_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::PacketUnicastTxCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_current_max_rate(cluster_t *cluster, uint64_t value) +attribute_t *create_current_max_rate(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::CurrentMaxRate::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint64(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint64(value)); } -attribute_t *create_overrun_count(cluster_t *cluster, uint64_t value) +attribute_t *create_overrun_count(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, WiFiNetworkDiagnostics::Attributes::OverrunCount::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint64(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint64(value)); } } /* attribute */ @@ -571,16 +573,16 @@ attribute_t *create_overrun_count(cluster_t *cluster, uint64_t value) namespace diagnostics_network_thread { namespace attribute { -attribute_t *create_channel(cluster_t *cluster, uint16_t value) +attribute_t *create_channel(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::Channel::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint16(value)); } -attribute_t *create_routing_role(cluster_t *cluster, uint8_t value) +attribute_t *create_routing_role(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::RoutingRole::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_enum8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } attribute_t *create_network_name(cluster_t *cluster, char *value, uint16_t length) @@ -589,16 +591,16 @@ attribute_t *create_network_name(cluster_t *cluster, char *value, uint16_t lengt ATTRIBUTE_FLAG_NONE, esp_matter_char_str(value, length)); } -attribute_t *create_pan_id(cluster_t *cluster, uint16_t value) +attribute_t *create_pan_id(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::PanId::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint16(value)); } -attribute_t *create_extended_pan_id(cluster_t *cluster, uint64_t value) +attribute_t *create_extended_pan_id(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint64(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint64(value)); } attribute_t *create_mesh_local_prefix(cluster_t *cluster, uint8_t *value, uint16_t length) @@ -619,34 +621,34 @@ attribute_t *create_route_table(cluster_t *cluster, uint8_t *value, uint16_t len ATTRIBUTE_FLAG_NONE, esp_matter_array(value, length, count)); } -attribute_t *create_extended_partition_id(cluster_t *cluster, uint32_t value) +attribute_t *create_partition_id(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::PartitionId::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint32(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint32(value)); } -attribute_t *create_weighting(cluster_t *cluster, uint8_t value) +attribute_t *create_weighting(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::Weighting::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } -attribute_t *create_data_version(cluster_t *cluster, uint8_t value) +attribute_t *create_data_version(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::DataVersion::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } -attribute_t *create_stable_data_version(cluster_t *cluster, uint8_t value) +attribute_t *create_stable_data_version(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } -attribute_t *create_leader_router_id(cluster_t *cluster, uint8_t value) +attribute_t *create_leader_router_id(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } attribute_t *create_security_policy(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) @@ -677,6 +679,51 @@ attribute_t *create_active_network_faults(cluster_t *cluster, uint8_t *value, ui } /* attribute */ } /* diagnostics_network_thread */ +namespace bridged_device_basic { +namespace attribute { + +attribute_t *create_bridged_device_basic_node_label(cluster_t *cluster, char *value, uint16_t length) +{ + return esp_matter::attribute::create(cluster, BridgedDeviceBasic::Attributes::NodeLabel::Id, + ATTRIBUTE_FLAG_NONVOLATILE | ATTRIBUTE_FLAG_WRITABLE, + esp_matter_char_str(value, length)); +} + +attribute_t *create_reachable(cluster_t *cluster, bool value) +{ + return esp_matter::attribute::create(cluster, BridgedDeviceBasic::Attributes::Reachable::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_bool(value)); +} + +} /* attribute */ +} /* bridged_device_basic */ + +namespace user_label { +namespace attribute { + +attribute_t *create_label_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, UserLabel::Attributes::LabelList::Id, + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE, + esp_matter_array(value, length, count)); +} + +} /* attribute */ +} /* user_label */ + +namespace fixed_label { +namespace attribute { + +attribute_t *create_label_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) +{ + return esp_matter::attribute::create(cluster, FixedLabel::Attributes::LabelList::Id, + ATTRIBUTE_FLAG_NONVOLATILE, esp_matter_array(value, length, count)); +} + +} /* attribute */ +} /* fixed_label */ + + namespace identify { namespace attribute { @@ -764,23 +811,25 @@ attribute_t *create_global_scene_control(cluster_t *cluster, bool value) esp_matter_bool(value)); } -attribute_t *create_on_time(cluster_t *cluster, uint16_t value) +attribute_t *create_on_time(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, OnOff::Attributes::OnTime::Id, ATTRIBUTE_FLAG_WRITABLE, - esp_matter_uint16(value)); + return esp_matter::attribute::create(cluster, OnOff::Attributes::OnTime::Id, + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint16(value)); } -attribute_t *create_off_wait_time(cluster_t *cluster, uint16_t value) +attribute_t *create_off_wait_time(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, OnOff::Attributes::OffWaitTime::Id, ATTRIBUTE_FLAG_WRITABLE, - esp_matter_uint16(value)); + return esp_matter::attribute::create(cluster, OnOff::Attributes::OffWaitTime::Id, + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint16(value)); } -attribute_t *create_start_up_on_off(cluster_t *cluster, uint8_t value) +attribute_t *create_start_up_on_off(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, OnOff::Attributes::StartUpOnOff::Id, ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NONVOLATILE | ATTRIBUTE_FLAG_NULLABLE, - esp_matter_enum8(value)); + esp_matter_nullable_enum8(value)); } } /* attribute */ @@ -789,16 +838,18 @@ attribute_t *create_start_up_on_off(cluster_t *cluster, uint8_t value) namespace level_control { namespace attribute { -attribute_t *create_current_level(cluster_t *cluster, uint8_t value) +attribute_t *create_current_level(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, LevelControl::Attributes::CurrentLevel::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, LevelControl::Attributes::CurrentLevel::Id, + ATTRIBUTE_FLAG_NONVOLATILE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint8(value)); } -attribute_t *create_on_level(cluster_t *cluster, uint8_t value) +attribute_t *create_on_level(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, LevelControl::Attributes::OnLevel::Id, ATTRIBUTE_FLAG_WRITABLE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, LevelControl::Attributes::OnLevel::Id, + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint8(value)); } attribute_t *create_options(cluster_t *cluster, uint8_t value, uint8_t min, uint8_t max) @@ -855,28 +906,32 @@ attribute_t *create_on_off_transition_time(cluster_t *cluster, uint16_t value) ATTRIBUTE_FLAG_WRITABLE, esp_matter_uint16(value)); } -attribute_t *create_on_transition_time(cluster_t* cluster, uint16_t value) +attribute_t *create_on_transition_time(cluster_t* cluster, nullable value) { return esp_matter::attribute::create(cluster, LevelControl::Attributes::OnTransitionTime::Id, - ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint16(value)); } -attribute_t *create_off_transition_time(cluster_t* cluster, uint16_t value) +attribute_t *create_off_transition_time(cluster_t* cluster, nullable value) { return esp_matter::attribute::create(cluster, LevelControl::Attributes::OffTransitionTime::Id, - ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint16(value)); } -attribute_t *create_default_move_rate(cluster_t* cluster, uint8_t value) +attribute_t *create_default_move_rate(cluster_t* cluster, nullable value) { return esp_matter::attribute::create(cluster, LevelControl::Attributes::DefaultMoveRate::Id, - ATTRIBUTE_FLAG_WRITABLE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint8(value)); } -attribute_t *create_start_up_current_level(cluster_t *cluster, uint8_t value) +attribute_t *create_start_up_current_level(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, LevelControl::Attributes::StartUpCurrentLevel::Id, - ATTRIBUTE_FLAG_WRITABLE, esp_matter_uint8(value)); + ATTRIBUTE_FLAG_WRITABLE | ATTRIBUTE_FLAG_NULLABLE | ATTRIBUTE_FLAG_NONVOLATILE, + esp_matter_nullable_uint8(value)); } } /* attribute */ @@ -951,10 +1006,11 @@ attribute_t *create_couple_color_temp_to_level_min_mireds(cluster_t *cluster, ui ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); } -attribute_t *create_startup_color_temperature_mireds(cluster_t *cluster, uint16_t value) +attribute_t *create_startup_color_temperature_mireds(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, ColorControl::Attributes::StartUpColorTemperatureMireds::Id, - ATTRIBUTE_FLAG_WRITABLE, esp_matter_uint16(value)); + ATTRIBUTE_FLAG_NULLABLE | ATTRIBUTE_FLAG_WRITABLE, + esp_matter_nullable_uint16(value)); } attribute_t *create_current_x(cluster_t *cluster, uint16_t value) @@ -1005,10 +1061,10 @@ attribute_t *create_color_loop_stored_enhanced_hue(cluster_t *cluster, uint16_t ATTRIBUTE_FLAG_NONE, esp_matter_uint16(value)); } -attribute_t *create_number_of_primaries(cluster_t *cluster, uint8_t value) +attribute_t *create_number_of_primaries(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, ColorControl::Attributes::NumberOfPrimaries::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::NumberOfPrimaries::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); } attribute_t *create_primary_n_x(cluster_t * cluster, uint16_t value, uint8_t index) @@ -1077,32 +1133,32 @@ attribute_t *create_primary_n_y(cluster_t * cluster, uint16_t value, uint8_t ind return NULL; } -attribute_t *create_primary_n_intensity(cluster_t * cluster, uint8_t value, uint8_t index) +attribute_t *create_primary_n_intensity(cluster_t * cluster, nullable value, uint8_t index) { switch (index) { case 1: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary1Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary1Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; case 2: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary2Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary2Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; case 3: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary3Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary3Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; case 4: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary4Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary4Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; case 5: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary5Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary5Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; case 6: - return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary6Intensity::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint8(value)); + return esp_matter::attribute::create(cluster, ColorControl::Attributes::Primary6Intensity::Id, + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_uint8(value)); break; default: break; @@ -1124,8 +1180,21 @@ attribute_t *create_fan_mode(cluster_t *cluster, uint8_t value) attribute_t *create_fan_mode_sequence(cluster_t *cluster, uint8_t value) { - return esp_matter::attribute::create(cluster, FanControl::Attributes::FanModeSequence::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_enum8(value)); + return esp_matter::attribute::create(cluster, FanControl::Attributes::FanModeSequence::Id, + ATTRIBUTE_FLAG_NONVOLATILE | ATTRIBUTE_FLAG_WRITABLE, esp_matter_enum8(value)); +} + +attribute_t *create_percent_setting(cluster_t *cluster, nullable value) +{ + return esp_matter::attribute::create(cluster, FanControl::Attributes::PercentSetting::Id, + ATTRIBUTE_FLAG_NULLABLE | ATTRIBUTE_FLAG_WRITABLE, + esp_matter_nullable_uint8(value)); +} + +attribute_t *create_percent_current(cluster_t *cluster, uint8_t value) +{ + return esp_matter::attribute::create(cluster, FanControl::Attributes::PercentSetting::Id, ATTRIBUTE_FLAG_NONE, + esp_matter_uint8(value)); } } /* attribute */ @@ -1134,10 +1203,10 @@ attribute_t *create_fan_mode_sequence(cluster_t *cluster, uint8_t value) namespace thermostat { namespace attribute { -attribute_t *create_local_temperature(cluster_t *cluster, uint16_t value) +attribute_t *create_local_temperature(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, Thermostat::Attributes::LocalTemperature::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_uint16(value)); + return esp_matter::attribute::create(cluster, Thermostat::Attributes::LocalTemperature::Id, ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_int16(value)); } attribute_t *create_occupied_cooling_setpoint(cluster_t *cluster, uint16_t value) @@ -1183,10 +1252,10 @@ attribute_t *create_system_mode(cluster_t *cluster, uint8_t value, uint8_t min, namespace door_lock { namespace attribute { -attribute_t *create_lock_state(cluster_t *cluster, uint8_t value) +attribute_t *create_lock_state(cluster_t *cluster, nullable value) { - return esp_matter::attribute::create(cluster, DoorLock::Attributes::LockState::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_enum8(value)); + return esp_matter::attribute::create(cluster, DoorLock::Attributes::LockState::Id, ATTRIBUTE_FLAG_NULLABLE, + esp_matter_nullable_uint8(value)); } attribute_t *create_lock_type(cluster_t *cluster, uint8_t value) @@ -1228,36 +1297,6 @@ attribute_t *create_supported_operating_modes(cluster_t *cluster, uint16_t value } /* attribute */ } /* door_lock */ -namespace bridged_device_basic { -namespace attribute { - -attribute_t *create_bridged_device_basic_node_label(cluster_t *cluster, char *value, uint16_t length) -{ - return esp_matter::attribute::create(cluster, BridgedDeviceBasic::Attributes::NodeLabel::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_char_str(value, length)); -} - -attribute_t *create_reachable(cluster_t *cluster, bool value) -{ - return esp_matter::attribute::create(cluster, BridgedDeviceBasic::Attributes::Reachable::Id, ATTRIBUTE_FLAG_NONE, - esp_matter_bool(value)); -} - -} /* attribute */ -} /* bridged_device_basic */ - -namespace fixed_label { -namespace attribute { - -attribute_t *create_label_list(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count) -{ - return esp_matter::attribute::create(cluster, FixedLabel::Attributes::LabelList::Id, ATTRIBUTE_FLAG_WRITABLE, - esp_matter_array(value, length, count)); -} - -} /* attribute */ -} /* fixed_label */ - namespace switch_cluster { namespace attribute { @@ -1285,22 +1324,22 @@ attribute_t *create_multi_press_max(cluster_t *cluster, uint8_t value) namespace temperature_measurement { namespace attribute { -attribute_t *create_temperature_measured_value(cluster_t *cluster, int16_t value) +attribute_t *create_temperature_measured_value(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, TemperatureMeasurement::Attributes::MeasuredValue::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_int16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int16(value)); } -attribute_t *create_temperature_min_measured_value(cluster_t *cluster, int16_t value) +attribute_t *create_temperature_min_measured_value(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, TemperatureMeasurement::Attributes::MinMeasuredValue::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_int16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int16(value)); } -attribute_t *create_temperature_max_measured_value(cluster_t *cluster, int16_t value) +attribute_t *create_temperature_max_measured_value(cluster_t *cluster, nullable value) { return esp_matter::attribute::create(cluster, TemperatureMeasurement::Attributes::MaxMeasuredValue::Id, - ATTRIBUTE_FLAG_NONE, esp_matter_int16(value)); + ATTRIBUTE_FLAG_NULLABLE, esp_matter_nullable_int16(value)); } } /* attribute */ diff --git a/components/esp_matter/esp_matter_attribute.h b/components/esp_matter/esp_matter_attribute.h index 0d92e7316..a236618ed 100644 --- a/components/esp_matter/esp_matter_attribute.h +++ b/components/esp_matter/esp_matter_attribute.h @@ -66,6 +66,10 @@ attribute_t *create_hardware_version_string(cluster_t *cluster, char *value, uin attribute_t *create_software_version(cluster_t *cluster, uint32_t value); attribute_t *create_software_version_string(cluster_t *cluster, char *value, uint16_t length); attribute_t *create_capability_minima(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); + +/** These attributes are optional for the cluster, but when added to this cluster, the value is maintained internally. + * If the attributes are added in some other cluster, then the value is not maintained internally. + **/ attribute_t *create_manufacturing_date(cluster_t *cluster, char *value, uint16_t length); attribute_t *create_part_number(cluster_t *cluster, char *value, uint16_t length); attribute_t *create_product_url(cluster_t *cluster, char *value, uint16_t length); @@ -88,7 +92,7 @@ namespace attribute { attribute_t *create_default_ota_providers(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_update_possible(cluster_t *cluster, bool value); attribute_t *create_update_state(cluster_t *cluster, uint8_t value); -attribute_t *create_update_state_progress(cluster_t *cluster, uint8_t value); +attribute_t *create_update_state_progress(cluster_t *cluster, nullable value); } /* attribute */ } /* ota_requestor */ @@ -109,9 +113,9 @@ attribute_t *create_networks(cluster_t *cluster, uint8_t *value, uint16_t length attribute_t *create_scan_max_time_seconds(cluster_t *cluster, uint8_t value); attribute_t *create_connect_max_time_seconds(cluster_t *cluster, uint8_t value); attribute_t *create_interface_enabled(cluster_t *cluster, bool value); -attribute_t *create_last_networking_status(cluster_t *cluster, uint8_t value); +attribute_t *create_last_networking_status(cluster_t *cluster, nullable value); attribute_t *create_last_network_id(cluster_t *cluster, uint8_t *value, uint16_t length); -attribute_t *create_last_connect_error_value(cluster_t *cluster, uint32_t value); +attribute_t *create_last_connect_error_value(cluster_t *cluster, nullable value); } /* attribute */ } /* network_commissioning */ @@ -154,36 +158,40 @@ attribute_t *create_max_group_keys_per_fabric(cluster_t *cluster, uint16_t value namespace diagnostics_network_wifi { namespace attribute { attribute_t *create_bssid(cluster_t *cluster, uint8_t *value, uint16_t length); -attribute_t *create_security_type(cluster_t *cluster, uint8_t value); -attribute_t *create_wifi_version(cluster_t *cluster, uint8_t value); -attribute_t *create_channel_number(cluster_t *cluster, uint16_t value); -attribute_t *create_rssi(cluster_t *cluster, int8_t value); -attribute_t *create_beacon_lost_count(cluster_t *cluster, uint32_t value); -attribute_t *create_beacon_rx_count(cluster_t *cluster, uint32_t value); -attribute_t *create_packet_multicast_rx_count(cluster_t *cluster, uint32_t value); -attribute_t *create_packet_multicast_tx_count(cluster_t *cluster, uint32_t value); -attribute_t *create_packet_unicast_rx_count(cluster_t *cluster, uint32_t value); -attribute_t *create_packet_unicast_tx_count(cluster_t *cluster, uint32_t value); -attribute_t *create_current_max_rate(cluster_t *cluster, uint64_t value); -attribute_t *create_overrun_count(cluster_t *cluster, uint64_t value); +attribute_t *create_security_type(cluster_t *cluster, nullable value); +attribute_t *create_wifi_version(cluster_t *cluster, nullable value); +attribute_t *create_channel_number(cluster_t *cluster, nullable value); +attribute_t *create_rssi(cluster_t *cluster, nullable value); + +/** These attributes are optional for the cluster, but when added to this cluster, the value is maintained internally. + * If the attributes are added in some other cluster, then the value is not maintained internally. + **/ +attribute_t *create_beacon_lost_count(cluster_t *cluster, nullable value); +attribute_t *create_beacon_rx_count(cluster_t *cluster, nullable value); +attribute_t *create_packet_multicast_rx_count(cluster_t *cluster, nullable value); +attribute_t *create_packet_multicast_tx_count(cluster_t *cluster, nullable value); +attribute_t *create_packet_unicast_rx_count(cluster_t *cluster, nullable value); +attribute_t *create_packet_unicast_tx_count(cluster_t *cluster, nullable value); +attribute_t *create_current_max_rate(cluster_t *cluster, nullable value); +attribute_t *create_overrun_count(cluster_t *cluster, nullable value); } /* attribute */ } /* diagnostics_network_wifi */ namespace diagnostics_network_thread { namespace attribute { -attribute_t *create_channel(cluster_t *cluster, uint16_t value); -attribute_t *create_routing_role(cluster_t *cluster, uint8_t value); +attribute_t *create_channel(cluster_t *cluster, nullable value); +attribute_t *create_routing_role(cluster_t *cluster, nullable value); attribute_t *create_network_name(cluster_t *cluster, char *value, uint16_t length); -attribute_t *create_pan_id(cluster_t *cluster, uint16_t value); -attribute_t *create_extended_pan_id(cluster_t *cluster, uint64_t value); +attribute_t *create_pan_id(cluster_t *cluster, nullable value); +attribute_t *create_extended_pan_id(cluster_t *cluster, nullable value); attribute_t *create_mesh_local_prefix(cluster_t *cluster, uint8_t *value, uint16_t length); attribute_t *create_neighbor_table(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_route_table(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); -attribute_t *create_extended_partition_id(cluster_t *cluster, uint32_t value); -attribute_t *create_weighting(cluster_t *cluster, uint8_t value); -attribute_t *create_data_version(cluster_t *cluster, uint8_t value); -attribute_t *create_stable_data_version(cluster_t *cluster, uint8_t value); -attribute_t *create_leader_router_id(cluster_t *cluster, uint8_t value); +attribute_t *create_extended_partition_id(cluster_t *cluster, nullable value); +attribute_t *create_weighting(cluster_t *cluster, nullable value); +attribute_t *create_data_version(cluster_t *cluster, nullable value); +attribute_t *create_stable_data_version(cluster_t *cluster, nullable value); +attribute_t *create_leader_router_id(cluster_t *cluster, nullable value); attribute_t *create_security_policy(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); attribute_t *create_channel_page0_mask(cluster_t *cluster, uint8_t *value, uint16_t length); attribute_t *create_operational_dataset_components(cluster_t *cluster, uint8_t *value, uint16_t length, uint16_t count); @@ -218,16 +226,16 @@ namespace on_off { namespace attribute { attribute_t *create_on_off(cluster_t *cluster, bool value); attribute_t *create_global_scene_control(cluster_t *cluster, bool value); -attribute_t *create_on_time(cluster_t *cluster, uint16_t value); -attribute_t *create_off_wait_time(cluster_t *cluster, uint16_t value); -attribute_t *create_start_up_on_off(cluster_t *cluster, uint8_t value); +attribute_t *create_on_time(cluster_t *cluster, nullable value); +attribute_t *create_off_wait_time(cluster_t *cluster, nullable value); +attribute_t *create_start_up_on_off(cluster_t *cluster, nullable value); } /* attribute */ } /* on_off */ namespace level_control { namespace attribute { -attribute_t *create_current_level(cluster_t *cluster, uint8_t value); -attribute_t *create_on_level(cluster_t *cluster, uint8_t value); +attribute_t *create_current_level(cluster_t *cluster, nullable value); +attribute_t *create_on_level(cluster_t *cluster, nullable value); attribute_t *create_options(cluster_t *cluster, uint8_t value, uint8_t min, uint8_t max); attribute_t *create_remaining_time(cluster_t *cluster, uint16_t value); attribute_t *create_min_level(cluster_t *cluster, uint8_t value); @@ -236,10 +244,10 @@ attribute_t *create_current_frequency(cluster_t *cluster, uint16_t value); attribute_t *create_min_frequency(cluster_t *cluster, uint16_t value); attribute_t *create_max_frequency(cluster_t *cluster, uint16_t value); attribute_t *create_on_off_transition_time(cluster_t *cluster, uint16_t value); -attribute_t *create_on_transition_time(cluster_t* cluster, uint16_t value); -attribute_t *create_off_transition_time(cluster_t* cluster, uint16_t value); -attribute_t *create_default_move_rate(cluster_t* cluster, uint8_t value); -attribute_t *create_start_up_current_level(cluster_t *cluster, uint8_t value); +attribute_t *create_on_transition_time(cluster_t* cluster, nullable value); +attribute_t *create_off_transition_time(cluster_t* cluster, nullable value); +attribute_t *create_default_move_rate(cluster_t* cluster, nullable value); +attribute_t *create_start_up_current_level(cluster_t *cluster, nullable value); } /* attribute */ } /* level_control */ @@ -256,7 +264,7 @@ attribute_t *create_color_temperature_mireds(cluster_t *cluster, uint16_t value) attribute_t *create_color_temp_physical_min_mireds(cluster_t *cluster, uint16_t value); attribute_t *create_color_temp_physical_max_mireds(cluster_t *cluster, uint16_t value); attribute_t *create_couple_color_temp_to_level_min_mireds(cluster_t *cluster, uint16_t value); -attribute_t *create_startup_color_temperature_mireds(cluster_t *cluster, uint16_t value); +attribute_t *create_startup_color_temperature_mireds(cluster_t *cluster, nullable value); attribute_t *create_current_x(cluster_t *cluster, uint16_t value); attribute_t *create_current_y(cluster_t *cluster, uint16_t value); attribute_t *create_enhanced_current_hue(cluster_t *cluster, uint16_t value); @@ -265,10 +273,10 @@ attribute_t *create_color_loop_direction(cluster_t *cluster, uint8_t value); attribute_t *create_color_loop_time(cluster_t *cluster, uint16_t value); attribute_t *create_color_loop_start_enhanced_hue(cluster_t *cluster, uint16_t value); attribute_t *create_color_loop_stored_enhanced_hue(cluster_t *cluster, uint16_t value); -attribute_t *create_number_of_primaries(cluster_t *cluster, uint8_t value); +attribute_t *create_number_of_primaries(cluster_t *cluster, nullable value); attribute_t *create_primary_n_x(cluster_t * cluster, uint16_t value, uint8_t index); attribute_t *create_primary_n_y(cluster_t * cluster, uint16_t value, uint8_t index); -attribute_t *create_primary_n_intensity(cluster_t * cluster, uint8_t value, uint8_t index); +attribute_t *create_primary_n_intensity(cluster_t * cluster, nullable value, uint8_t index); } /* attribute */ } /* color_control */ @@ -276,12 +284,14 @@ namespace fan_control { namespace attribute { attribute_t *create_fan_mode(cluster_t *cluster, uint8_t value); attribute_t *create_fan_mode_sequence(cluster_t *cluster, uint8_t value); +attribute_t *create_percent_setting(cluster_t *cluster, nullable value); +attribute_t *create_percent_current(cluster_t *cluster, uint8_t value); } /* attribute */ } /* fan_control */ namespace thermostat { namespace attribute { -attribute_t *create_local_temperature(cluster_t *cluster, uint16_t value); +attribute_t *create_local_temperature(cluster_t *cluster, nullable value); attribute_t *create_occupied_cooling_setpoint(cluster_t *cluster, uint16_t value); attribute_t *create_occupied_heating_setpoint(cluster_t *cluster, uint16_t value); attribute_t *create_control_sequence_of_operation(cluster_t *cluster, uint8_t value, uint8_t min, uint8_t max); @@ -291,7 +301,7 @@ attribute_t *create_system_mode(cluster_t *cluster, uint8_t value, uint8_t min, namespace door_lock { namespace attribute { -attribute_t *create_lock_state(cluster_t *cluster, uint8_t value); +attribute_t *create_lock_state(cluster_t *cluster, nullable value); attribute_t *create_lock_type(cluster_t *cluster, uint8_t value); attribute_t *create_actuator_enabled(cluster_t *cluster, bool value); attribute_t *create_auto_relock_time(cluster_t *cluster, uint32_t value); @@ -323,9 +333,9 @@ attribute_t *create_multi_press_max(cluster_t *cluster, uint8_t value); namespace temperature_measurement { namespace attribute { -attribute_t *create_temperature_measured_value(cluster_t *cluster, int16_t value); -attribute_t *create_temperature_min_measured_value(cluster_t *cluster, int16_t value); -attribute_t *create_temperature_max_measured_value(cluster_t *cluster, int16_t value); +attribute_t *create_temperature_measured_value(cluster_t *cluster, nullable value); +attribute_t *create_temperature_min_measured_value(cluster_t *cluster, nullable value); +attribute_t *create_temperature_max_measured_value(cluster_t *cluster, nullable value); } /* attribute */ } /* temperature_measurement */ diff --git a/components/esp_matter/esp_matter_attribute_utils.cpp b/components/esp_matter/esp_matter_attribute_utils.cpp index a4c17c984..7923e7441 100644 --- a/components/esp_matter/esp_matter_attribute_utils.cpp +++ b/components/esp_matter/esp_matter_attribute_utils.cpp @@ -64,6 +64,19 @@ esp_matter_attr_val_t esp_matter_int(int val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_int(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.i); + } else { + attr_val.val.i = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_float(float val) { esp_matter_attr_val_t attr_val = { @@ -75,6 +88,19 @@ esp_matter_attr_val_t esp_matter_float(float val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_float(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.f); + } else { + attr_val.val.i = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_int8(int8_t val) { esp_matter_attr_val_t attr_val = { @@ -86,6 +112,19 @@ esp_matter_attr_val_t esp_matter_int8(int8_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_int8(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_INT8, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.i8); + } else { + attr_val.val.i8 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_uint8(uint8_t val) { esp_matter_attr_val_t attr_val = { @@ -97,6 +136,19 @@ esp_matter_attr_val_t esp_matter_uint8(uint8_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_uint8(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_UINT8, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u8); + } else { + attr_val.val.u8 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_int16(int16_t val) { esp_matter_attr_val_t attr_val = { @@ -108,6 +160,19 @@ esp_matter_attr_val_t esp_matter_int16(int16_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_int16(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_INT16, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.i16); + } else { + attr_val.val.i16 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_uint16(uint16_t val) { esp_matter_attr_val_t attr_val = { @@ -119,6 +184,43 @@ esp_matter_attr_val_t esp_matter_uint16(uint16_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_uint16(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_UINT16, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u16); + } else { + attr_val.val.u16 = val.value(); + } + return attr_val; +} + +esp_matter_attr_val_t esp_matter_int32(int32_t val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_INT32, + .val = { + .i32 = val, + }, + }; + return attr_val; +} + +esp_matter_attr_val_t esp_matter_nullable_int32(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_INT32, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.i32); + } else { + attr_val.val.i32 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_uint32(uint32_t val) { esp_matter_attr_val_t attr_val = { @@ -130,6 +232,43 @@ esp_matter_attr_val_t esp_matter_uint32(uint32_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_uint32(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_UINT32, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u32); + } else { + attr_val.val.u32 = val.value(); + } + return attr_val; +} + +esp_matter_attr_val_t esp_matter_int64(int64_t val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_INT64, + .val = { + .i64 = val, + }, + }; + return attr_val; +} + +esp_matter_attr_val_t esp_matter_nullable_int64(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_INT64, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.i64); + } else { + attr_val.val.i64 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_uint64(uint64_t val) { esp_matter_attr_val_t attr_val = { @@ -141,6 +280,19 @@ esp_matter_attr_val_t esp_matter_uint64(uint64_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_uint64(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_UINT64, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u64); + } else { + attr_val.val.u64 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_enum8(uint8_t val) { esp_matter_attr_val_t attr_val = { @@ -152,6 +304,19 @@ esp_matter_attr_val_t esp_matter_enum8(uint8_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_enum8(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u8); + } else { + attr_val.val.u8 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_bitmap8(uint8_t val) { esp_matter_attr_val_t attr_val = { @@ -163,6 +328,19 @@ esp_matter_attr_val_t esp_matter_bitmap8(uint8_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_bitmap8(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u8); + } else { + attr_val.val.u8 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_bitmap16(uint16_t val) { esp_matter_attr_val_t attr_val = { @@ -174,6 +352,19 @@ esp_matter_attr_val_t esp_matter_bitmap16(uint16_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_bitmap16(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u16); + } else { + attr_val.val.u16 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_bitmap32(uint32_t val) { esp_matter_attr_val_t attr_val = { @@ -185,6 +376,19 @@ esp_matter_attr_val_t esp_matter_bitmap32(uint32_t val) return attr_val; } +esp_matter_attr_val_t esp_matter_nullable_bitmap32(nullable val) +{ + esp_matter_attr_val_t attr_val = { + .type = ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32, + }; + if (val.is_null()) { + chip::app::NumericAttributeTraits::SetNull(attr_val.val.u32); + } else { + attr_val.val.u32 = val.value(); + } + return attr_val; +} + esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size) { uint16_t data_size_len = 1; /* Number of bytes used to store the length */ @@ -244,138 +448,388 @@ static callback_t attribute_callback = NULL; static esp_err_t console_handler(int argc, char **argv) { - if (argc == 5 && strncmp(argv[0], "set", sizeof("set")) == 0) { - uint16_t endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - uint32_t cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - uint32_t attribute_id = strtol((const char *)&argv[3][2], NULL, 16); + if (argc < 4) { + ESP_LOGE(TAG, "The arguments for this command is invalid"); + return ESP_ERR_INVALID_ARG; + } - /* Get type from matter_attribute */ - const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, - attribute_id); - if (!matter_attribute) { - ESP_LOGE(TAG, "Matter attribute not found"); - return ESP_ERR_INVALID_ARG; - } + uint16_t endpoint_id = strtol((const char *)&argv[0][2], NULL, 16); + uint32_t cluster_id = strtol((const char *)&argv[1][2], NULL, 16); + uint32_t attribute_id = strtol((const char *)&argv[2][2], NULL, 16); - /* Use the type to create the val and then update te attribute */ - esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); - esp_matter_attr_val_t val = esp_matter_invalid(NULL); - if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { - bool value = atoi(argv[4]); - val = esp_matter_bool(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT8) { - int8_t value = atoi(argv[4]); - val = esp_matter_int8(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_uint8(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT16) { - int16_t value = atoi(argv[4]); - val = esp_matter_int16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { - uint16_t value = atoi(argv[4]); - val = esp_matter_uint16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { - uint32_t value = atoi(argv[4]); - val = esp_matter_uint32(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { - uint64_t value = atoi(argv[4]); - val = esp_matter_uint64(value); - } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { - char *value = argv[4]; - val = esp_matter_char_str(value, strlen(value)); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_bitmap8(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { - uint16_t value = atoi(argv[4]); - val = esp_matter_bitmap16(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { - uint32_t value = atoi(argv[4]); - val = esp_matter_bitmap32(value); - } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { - uint8_t value = atoi(argv[4]); - val = esp_matter_enum8(value); + /* Get type from matter_attribute */ + const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); + return ESP_ERR_INVALID_ARG; + } + + /* Use the type to create the val and then update te attribute */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + bool value = atoi(argv[3]); + val = esp_matter_bool(value); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_int8(nullable()); + } else { + int8_t value = atoi(argv[3]); + val = esp_matter_nullable_int8(value); + } } else { - ESP_LOGE(TAG, "Type not handled: %d", type); - return ESP_ERR_INVALID_ARG; - } - update(endpoint_id, cluster_id, attribute_id, &val); - } else if (argc == 4 && strncmp(argv[0], "get", sizeof("get")) == 0) { - uint16_t endpoint_id = strtol((const char *)&argv[1][2], NULL, 16); - uint32_t cluster_id = strtol((const char *)&argv[2][2], NULL, 16); - uint32_t attribute_id = strtol((const char *)&argv[3][2], NULL, 16); - - /* Get type from matter_attribute */ - const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, - attribute_id); - if (!matter_attribute) { - ESP_LOGE(TAG, "Matter attribute not found"); - return ESP_ERR_INVALID_ARG; - } - - /* Use the type to read the raw value and then print */ - esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); - esp_matter_attr_val_t val = esp_matter_invalid(NULL); - if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { - bool value = false; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bool(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT8) { - int8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + int8_t value = atoi(argv[3]); val = esp_matter_int8(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint8(value); - } else if (type == ESP_MATTER_VAL_TYPE_INT16) { - int16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_int16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { - uint16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint16(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { - uint32_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint32(value); - } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { - uint64_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_uint64(value); - } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { - /* Get raw value */ - char value[256] = {0}; /* It can go upto 256 since only 1 byte (first) is used for size */ - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - /* Get val from raw value */ - val = esp_matter_char_str(NULL, 0); - int data_size_len = val.val.a.t - val.val.a.s; - int data_count = 0; - memcpy(&data_count, &value[0], data_size_len); - val = esp_matter_char_str((char *)(value + data_size_len), data_count); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap8(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { - uint16_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap16(value); - } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { - uint32_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_bitmap32(value); - } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { - uint8_t value = 0; - get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); - val = esp_matter_enum8(value); - } else { - ESP_LOGE(TAG, "Type not handled: %d", type); - return ESP_ERR_INVALID_ARG; } - val_print(endpoint_id, cluster_id, attribute_id, &val); + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_uint8(nullable()); + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_nullable_uint8(value); + } + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_uint8(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_int16(nullable()); + } else { + int16_t value = atoi(argv[3]); + val = esp_matter_nullable_int16(value); + } + } else { + int16_t value = atoi(argv[3]); + val = esp_matter_int16(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_uint16(nullable()); + } else { + uint16_t value = atoi(argv[3]); + val = esp_matter_nullable_uint16(value); + } + } else { + uint16_t value = atoi(argv[3]); + val = esp_matter_uint16(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT32) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_int32(nullable()); + } else { + int32_t value = atoi(argv[3]); + val = esp_matter_nullable_int32(value); + } + } else { + int32_t value = atoi(argv[3]); + val = esp_matter_int32(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_uint32(nullable()); + } else { + uint32_t value = atoi(argv[3]); + val = esp_matter_nullable_uint32(value); + } + } else { + uint32_t value = atoi(argv[3]); + val = esp_matter_uint32(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT64) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_int64(nullable()); + } else { + int64_t value = atoi(argv[3]); + val = esp_matter_nullable_int64(value); + } + } else { + int64_t value = atoi(argv[3]); + val = esp_matter_int64(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_uint64(nullable()); + } else { + uint64_t value = atoi(argv[3]); + val = esp_matter_nullable_uint64(value); + } + } else { + uint64_t value = atoi(argv[3]); + val = esp_matter_uint64(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + char *value = argv[3]; + val = esp_matter_char_str(value, strlen(value)); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_bitmap8(nullable()); + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_nullable_bitmap8(value); + } + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_bitmap8(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_bitmap16(nullable()); + } else { + uint16_t value = atoi(argv[3]); + val = esp_matter_nullable_bitmap16(value); + } + } else { + uint16_t value = atoi(argv[3]); + val = esp_matter_bitmap16(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_bitmap32(nullable()); + } else { + uint32_t value = atoi(argv[3]); + val = esp_matter_nullable_bitmap32(value); + } + } else { + uint32_t value = atoi(argv[3]); + val = esp_matter_bitmap32(value); + } + } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { + if (matter_attribute->IsNullable()) { + if (strncmp(argv[3], "null", sizeof("null")) == 0) { + val = esp_matter_nullable_enum8(nullable()); + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_nullable_enum8(value); + } + } else { + uint8_t value = atoi(argv[3]); + val = esp_matter_enum8(value); + } + } else { + ESP_LOGE(TAG, "Type not handled: %d", type); + return ESP_ERR_INVALID_ARG; + } + return update(endpoint_id, cluster_id, attribute_id, &val); +} + +static esp_err_t console_get_handler(int argc, char **argv) +{ + if (argc < 3) { + ESP_LOGE(TAG, "The arguments for this command is invalid"); + return ESP_ERR_INVALID_ARG; + } + uint16_t endpoint_id = strtol((const char *)&argv[0][2], NULL, 16); + uint32_t cluster_id = strtol((const char *)&argv[1][2], NULL, 16); + uint32_t attribute_id = strtol((const char *)&argv[2][2], NULL, 16); + + /* Get type from matter_attribute */ + const EmberAfAttributeMetadata *matter_attribute = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); + if (!matter_attribute) { + ESP_LOGE(TAG, "Matter attribute not found"); + return ESP_ERR_INVALID_ARG; + } + + /* Use the type to read the raw value and then print */ + esp_matter_val_type_t type = get_val_type_from_attribute_type(matter_attribute->attributeType); + esp_matter_attr_val_t val = esp_matter_invalid(NULL); + if (type == ESP_MATTER_VAL_TYPE_BOOLEAN) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + val = esp_matter_bool(Traits::StorageToWorking(value)); + } else if (type == ESP_MATTER_VAL_TYPE_INT8) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_int8(nullable()); + } else { + val = esp_matter_nullable_int8(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_int8(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT8) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_uint8(nullable()); + } else { + val = esp_matter_nullable_uint8(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_uint8(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT16) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_int16(nullable()); + } else { + val = esp_matter_nullable_int16(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_int16(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT16) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_uint16(nullable()); + } else { + val = esp_matter_nullable_uint16(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_uint16(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT32) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_int32(nullable()); + } else { + val = esp_matter_nullable_int32(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_int32(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT32) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_uint32(nullable()); + } else { + val = esp_matter_nullable_uint32(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_uint32(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_INT64) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_int64(nullable()); + } else { + val = esp_matter_nullable_int64(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_int64(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_UINT64) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_uint64(nullable()); + } else { + val = esp_matter_nullable_uint64(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_uint64(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { + /* Get raw value */ + char value[256] = {0}; /* It can go upto 256 since only 1 byte (first) is used for size */ + get_val_raw(endpoint_id, cluster_id, attribute_id, (uint8_t *)&value, sizeof(value)); + /* Get val from raw value */ + val = esp_matter_char_str(NULL, 0); + int data_size_len = val.val.a.t - val.val.a.s; + int data_count = 0; + memcpy(&data_count, &value[0], data_size_len); + val = esp_matter_char_str((char *)(value + data_size_len), data_count); + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP8) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_bitmap8(nullable()); + } else { + val = esp_matter_nullable_bitmap8(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_bitmap8(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP16) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_bitmap16(nullable()); + } else { + val = esp_matter_nullable_bitmap16(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_bitmap16(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_BITMAP32) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_bitmap32(nullable()); + } else { + val = esp_matter_nullable_bitmap32(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_bitmap32(Traits::StorageToWorking(value)); + } + } else if (type == ESP_MATTER_VAL_TYPE_ENUM8) { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType value; + uint8_t *read_able = Traits::ToAttributeStoreRepresentation(value); + get_val_raw(endpoint_id, cluster_id, attribute_id, read_able, sizeof(value)); + if (matter_attribute->IsNullable()) { + if (Traits::IsNullValue(value)) { + val = esp_matter_nullable_enum8(nullable()); + } else { + val = esp_matter_nullable_enum8(Traits::StorageToWorking(value)); + } + } else { + val = esp_matter_enum8(Traits::StorageToWorking(value)); + } } else { ESP_LOGE(TAG, "Incorrect arguments"); return ESP_ERR_INVALID_ARG; @@ -503,6 +957,50 @@ static esp_matter_val_type_t get_val_type_from_attribute_type(int attribute_type return ESP_MATTER_VAL_TYPE_INVALID; } +bool val_is_null(esp_matter_attr_val_t *val) +{ + switch (val->type) { + case ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.i); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT8: + case ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.u8); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT16: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.u16); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT32: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.u32); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT64: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.u64); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_INT8: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.i8); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_INT16: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.i16); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_INT32: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.i32); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_INT64: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.i64); + break; + case ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT: + return chip::app::NumericAttributeTraits::IsNullValue(val->val.f); + break; + default: + return false; + break; + } + return false; +} + esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeType *attribute_type, uint16_t *attribute_size, uint8_t *value) { @@ -515,23 +1013,31 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(bool); } if (value) { - memcpy(value, (uint8_t *)&val->val.b, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + Traits::WorkingToStorage(val->val.b, *value); } break; case ESP_MATTER_VAL_TYPE_INTEGER: + case ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER: if (attribute_type) { *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; } if (attribute_size) { - *attribute_size = sizeof(uint16_t); + *attribute_size = sizeof(int); } if (value) { - memcpy(value, (uint8_t *)&val->val.i, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.i)) { + Traits::SetNull(*(int *)value); + } else { + Traits::WorkingToStorage(val->val.i, *(int *)value); + } } break; case ESP_MATTER_VAL_TYPE_FLOAT: + case ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT: if (attribute_type) { *attribute_type = ZCL_SINGLE_ATTRIBUTE_TYPE; } @@ -539,7 +1045,12 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(float); } if (value) { - memcpy(value, (uint8_t *)&val->val.f, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.f)) { + Traits::SetNull(*(float *)value); + } else { + Traits::WorkingToStorage(val->val.f, *(float *)value); + } } break; @@ -586,6 +1097,7 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp break; case ESP_MATTER_VAL_TYPE_INT8: + case ESP_MATTER_VAL_TYPE_NULLABLE_INT8: if (attribute_type) { *attribute_type = ZCL_INT8S_ATTRIBUTE_TYPE; } @@ -593,11 +1105,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(int8_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.i8, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.i8)) { + Traits::SetNull(*(int8_t *)value); + } else { + Traits::WorkingToStorage(val->val.i8, *(int8_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_UINT8: + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT8: if (attribute_type) { *attribute_type = ZCL_INT8U_ATTRIBUTE_TYPE; } @@ -605,11 +1123,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint8_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u8)) { + Traits::SetNull(*(uint8_t *)value); + } else { + Traits::WorkingToStorage(val->val.u8, *(uint8_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_INT16: + case ESP_MATTER_VAL_TYPE_NULLABLE_INT16: if (attribute_type) { *attribute_type = ZCL_INT16S_ATTRIBUTE_TYPE; } @@ -617,11 +1141,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(int16_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.i16, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.i16)) { + Traits::SetNull(*(int16_t *)value); + } else { + Traits::WorkingToStorage(val->val.i16, *(int16_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_UINT16: + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT16: if (attribute_type) { *attribute_type = ZCL_INT16U_ATTRIBUTE_TYPE; } @@ -629,11 +1159,35 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint16_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u16, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u16)) { + Traits::SetNull(*(uint16_t *)value); + } else { + Traits::WorkingToStorage(val->val.u16, *(uint16_t *)value); + } + } + break; + + case ESP_MATTER_VAL_TYPE_INT32: + case ESP_MATTER_VAL_TYPE_NULLABLE_INT32: + if (attribute_type) { + *attribute_type = ZCL_INT32S_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(int32_t); + } + if (value) { + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.i32)) { + Traits::SetNull(*(int32_t *)value); + } else { + Traits::WorkingToStorage(val->val.i32, *(int32_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_UINT32: + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT32: if (attribute_type) { *attribute_type = ZCL_INT32U_ATTRIBUTE_TYPE; } @@ -641,11 +1195,35 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint32_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u32, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u32)) { + Traits::SetNull(*(uint32_t *)value); + } else { + Traits::WorkingToStorage(val->val.u32, *(uint32_t *)value); + } + } + break; + + case ESP_MATTER_VAL_TYPE_INT64: + case ESP_MATTER_VAL_TYPE_NULLABLE_INT64: + if (attribute_type) { + *attribute_type = ZCL_INT64S_ATTRIBUTE_TYPE; + } + if (attribute_size) { + *attribute_size = sizeof(int64_t); + } + if (value) { + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.i64)) { + Traits::SetNull(*(int64_t *)value); + } else { + Traits::WorkingToStorage(val->val.i64, *(int64_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_UINT64: + case ESP_MATTER_VAL_TYPE_NULLABLE_UINT64: if (attribute_type) { *attribute_type = ZCL_INT64U_ATTRIBUTE_TYPE; } @@ -653,11 +1231,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint64_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u64, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u64)) { + Traits::SetNull(*(uint64_t *)value); + } else { + Traits::WorkingToStorage(val->val.i8, *(uint64_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_ENUM8: + case ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8: if (attribute_type) { *attribute_type = ZCL_ENUM8_ATTRIBUTE_TYPE; } @@ -665,11 +1249,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint8_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u8)) { + Traits::SetNull(*(uint8_t *)value); + } else { + Traits::WorkingToStorage(val->val.u8, *(uint8_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_BITMAP8: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8: if (attribute_type) { *attribute_type = ZCL_BITMAP8_ATTRIBUTE_TYPE; } @@ -677,11 +1267,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint8_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u8, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u8)) { + Traits::SetNull(*(uint8_t *)value); + } else { + Traits::WorkingToStorage(val->val.u8, *(uint8_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_BITMAP16: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16: if (attribute_type) { *attribute_type = ZCL_BITMAP16_ATTRIBUTE_TYPE; } @@ -689,11 +1285,17 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint16_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u16, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u16)) { + Traits::SetNull(*(uint16_t *)value); + } else { + Traits::WorkingToStorage(val->val.u16, *(uint16_t *)value); + } } break; case ESP_MATTER_VAL_TYPE_BITMAP32: + case ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32: if (attribute_type) { *attribute_type = ZCL_BITMAP32_ATTRIBUTE_TYPE; } @@ -701,7 +1303,12 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp *attribute_size = sizeof(uint32_t); } if (value) { - memcpy(value, (uint8_t *)&val->val.u32, *attribute_size); + using Traits = chip::app::NumericAttributeTraits; + if ((val->type & ESP_MATTER_VAL_NULLANLE_BASE) && Traits::IsNullValue(val->val.u32)) { + Traits::SetNull(*(uint32_t *)value); + } else { + Traits::WorkingToStorage(val->val.i8, *(uint32_t *)value); + } } break; @@ -714,12 +1321,14 @@ esp_err_t get_data_from_attr_val(esp_matter_attr_val_t *val, EmberAfAttributeTyp } static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttributeType attribute_type, - uint16_t attribute_size, uint8_t *value) + uint16_t attribute_size, uint8_t *value, + const EmberAfAttributeMetadata * attribute_metadata) { switch (attribute_type) { case ZCL_BOOLEAN_ATTRIBUTE_TYPE: { - bool attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(bool)); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); *val = esp_matter_bool(attribute_value); break; } @@ -752,65 +1361,178 @@ static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttri } case ZCL_INT8S_ATTRIBUTE_TYPE: { - int8_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(int8_t)); - *val = esp_matter_int8(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_int8(nullable()); + } else { + *val = esp_matter_nullable_int8(attribute_value); + } + } else { + *val = esp_matter_int8(attribute_value); + } break; } case ZCL_INT8U_ATTRIBUTE_TYPE: { - uint8_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); - *val = esp_matter_uint8(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_uint8(nullable()); + } else { + *val = esp_matter_nullable_uint8(attribute_value); + } + } else { + *val = esp_matter_uint8(attribute_value); + } break; } case ZCL_INT16S_ATTRIBUTE_TYPE: { - int16_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(int16_t)); - *val = esp_matter_int16(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_int16(nullable()); + } else { + *val = esp_matter_nullable_int16(attribute_value); + } + } else { + *val = esp_matter_int16(attribute_value); + } break; } case ZCL_INT16U_ATTRIBUTE_TYPE: { - uint16_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint16_t)); - *val = esp_matter_uint16(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_uint16(nullable()); + } else { + *val = esp_matter_nullable_uint16(attribute_value); + } + } else { + *val = esp_matter_uint16(attribute_value); + } + break; + } + + case ZCL_INT32S_ATTRIBUTE_TYPE: { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_int32(nullable()); + } else { + *val = esp_matter_nullable_int32(attribute_value); + } + } else { + *val = esp_matter_int32(attribute_value); + } break; } case ZCL_INT32U_ATTRIBUTE_TYPE: { - uint32_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint32_t)); - *val = esp_matter_uint32(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_uint32(nullable()); + } else { + *val = esp_matter_nullable_uint32(attribute_value); + } + } else { + *val = esp_matter_uint32(attribute_value); + } + break; + } + + case ZCL_INT64S_ATTRIBUTE_TYPE: { + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_int64(nullable()); + } else { + *val = esp_matter_nullable_int64(attribute_value); + } + } else { + *val = esp_matter_int64(attribute_value); + } break; } case ZCL_INT64U_ATTRIBUTE_TYPE: { - uint64_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint64_t)); - *val = esp_matter_uint64(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_uint64(nullable()); + } else { + *val = esp_matter_nullable_uint64(attribute_value); + } + } else { + *val = esp_matter_uint64(attribute_value); + } break; } case ZCL_ENUM8_ATTRIBUTE_TYPE: { - uint8_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); - *val = esp_matter_enum8(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_enum8(nullable()); + } else { + *val = esp_matter_nullable_enum8(attribute_value); + } + } else { + *val = esp_matter_enum8(attribute_value); + } break; } case ZCL_BITMAP8_ATTRIBUTE_TYPE: { - uint8_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint8_t)); - *val = esp_matter_bitmap8(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_bitmap8(nullable()); + } else { + *val = esp_matter_nullable_bitmap8(attribute_value); + } + } else { + *val = esp_matter_bitmap8(attribute_value); + } break; } case ZCL_BITMAP16_ATTRIBUTE_TYPE: { - uint16_t attribute_value = 0; - memcpy((uint8_t *)&attribute_value, value, sizeof(uint16_t)); - *val = esp_matter_bitmap16(attribute_value); + using Traits = chip::app::NumericAttributeTraits; + Traits::StorageType attribute_value; + memcpy((uint8_t *)&attribute_value, value, sizeof(Traits::StorageType)); + if (attribute_metadata->IsNullable()) { + if (Traits::IsNullValue(attribute_value)) { + *val = esp_matter_nullable_bitmap16(nullable()); + } else { + *val = esp_matter_nullable_bitmap16(attribute_value); + } + } else { + *val = esp_matter_bitmap16(attribute_value); + } break; } @@ -824,29 +1546,44 @@ static esp_err_t get_attr_val_from_data(esp_matter_attr_val_t *val, EmberAfAttri void val_print(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) { + if (val_is_null(val)) { + ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is null **********", endpoint_id, + cluster_id, attribute_id); + return; + } + if (val->type == ESP_MATTER_VAL_TYPE_BOOLEAN) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.b); - } else if (val->type == ESP_MATTER_VAL_TYPE_INTEGER) { + } else if (val->type == ESP_MATTER_VAL_TYPE_INTEGER || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.i); - } else if (val->type == ESP_MATTER_VAL_TYPE_FLOAT) { + } else if (val->type == ESP_MATTER_VAL_TYPE_FLOAT || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %f **********", endpoint_id, cluster_id, attribute_id, val->val.f); } else if (val->type == ESP_MATTER_VAL_TYPE_UINT8 || val->type == ESP_MATTER_VAL_TYPE_BITMAP8 - || val->type == ESP_MATTER_VAL_TYPE_ENUM8) { + || val->type == ESP_MATTER_VAL_TYPE_ENUM8 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT8 + || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.u8); - } else if (val->type == ESP_MATTER_VAL_TYPE_INT16) { + } else if (val->type == ESP_MATTER_VAL_TYPE_INT16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INT16) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.i16); - } else if (val->type == ESP_MATTER_VAL_TYPE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_BITMAP16) { + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_BITMAP16 + || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT16 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.u16); - } else if (val->type == ESP_MATTER_VAL_TYPE_UINT32 || val->type == ESP_MATTER_VAL_TYPE_BITMAP32) { + } else if (val->type == ESP_MATTER_VAL_TYPE_INT32|| val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INT32) { + ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, + cluster_id, attribute_id, val->val.i32); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT32 || val->type == ESP_MATTER_VAL_TYPE_BITMAP32 + || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT32 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %d **********", endpoint_id, cluster_id, attribute_id, val->val.u32); - } else if (val->type == ESP_MATTER_VAL_TYPE_UINT64) { + } else if (val->type == ESP_MATTER_VAL_TYPE_INT64 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_INT64) { + ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %lld **********", endpoint_id, + cluster_id, attribute_id, val->val.i64); + } else if (val->type == ESP_MATTER_VAL_TYPE_UINT64 || val->type == ESP_MATTER_VAL_TYPE_NULLABLE_UINT64) { ESP_LOGI(TAG, "********** Endpoint 0x%04X's Cluster 0x%04X's Attribute 0x%04X is %lld **********", endpoint_id, cluster_id, attribute_id, val->val.u64); } else if (val->type == ESP_MATTER_VAL_TYPE_CHAR_STRING) { @@ -936,8 +1673,10 @@ Status MatterPreAttributeChangeCallback(const chip::app::ConcreteAttributePath & uint16_t endpoint_id = path.mEndpointId; uint32_t cluster_id = path.mClusterId; uint32_t attribute_id = path.mAttributeId; + const EmberAfAttributeMetadata *attribute_metadata = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); esp_matter_attr_val_t val = esp_matter_invalid(NULL); - attribute::get_attr_val_from_data(&val, type, size, value); + attribute::get_attr_val_from_data(&val, type, size, value, attribute_metadata); /* Print */ attribute::val_print(endpoint_id, cluster_id, attribute_id, &val); @@ -956,8 +1695,10 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &p uint16_t endpoint_id = path.mEndpointId; uint32_t cluster_id = path.mClusterId; uint32_t attribute_id = path.mAttributeId; + const EmberAfAttributeMetadata *attribute_metadata = emberAfLocateAttributeMetadata(endpoint_id, cluster_id, + attribute_id); esp_matter_attr_val_t val = esp_matter_invalid(NULL); - attribute::get_attr_val_from_data(&val, type, size, value); + attribute::get_attr_val_from_data(&val, type, size, value, attribute_metadata); /* Callback to application */ execute_callback(attribute::POST_UPDATE, endpoint_id, cluster_id, attribute_id, &val); @@ -1023,7 +1764,7 @@ EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint_id, Clus /* This creates a new variable val, and stores the new attribute value in the new variable. The value in esp-matter data model is updated only when attribute::set_val() is called */ esp_matter_attr_val_t val = esp_matter_invalid(NULL); - attribute::get_attr_val_from_data(&val, matter_attribute->attributeType, matter_attribute->size, buffer); + attribute::get_attr_val_from_data(&val, matter_attribute->attributeType, matter_attribute->size, buffer, matter_attribute); int flags = attribute::get_flags(attribute); if (flags & ATTRIBUTE_FLAG_OVERRIDE) { diff --git a/components/esp_matter/esp_matter_attribute_utils.h b/components/esp_matter/esp_matter_attribute_utils.h index 3a9d36d75..49d15dfb5 100644 --- a/components/esp_matter/esp_matter_attribute_utils.h +++ b/components/esp_matter/esp_matter_attribute_utils.h @@ -18,6 +18,8 @@ #include #include +#include + /** Remap attribute values * * This can be used to remap attribute values to different ranges. @@ -33,42 +35,64 @@ */ #define REMAP_TO_RANGE_INVERSE(value, factor) (factor / value) +/* Nullable base for nullable attribute */ +#define ESP_MATTER_VAL_NULLANLE_BASE 0x80 + /** ESP Matter Attribute Value type */ typedef enum { /** Invalid */ ESP_MATTER_VAL_TYPE_INVALID = 0, /** Boolean */ - ESP_MATTER_VAL_TYPE_BOOLEAN, + ESP_MATTER_VAL_TYPE_BOOLEAN = 1, /** Integer. Mapped to a 32 bit signed integer */ - ESP_MATTER_VAL_TYPE_INTEGER, + ESP_MATTER_VAL_TYPE_INTEGER = 2, /** Floating point number */ - ESP_MATTER_VAL_TYPE_FLOAT, + ESP_MATTER_VAL_TYPE_FLOAT = 3, /** Array Eg. [1,2,3] */ - ESP_MATTER_VAL_TYPE_ARRAY, + ESP_MATTER_VAL_TYPE_ARRAY = 4, /** Char String Eg. "123" */ - ESP_MATTER_VAL_TYPE_CHAR_STRING, + ESP_MATTER_VAL_TYPE_CHAR_STRING = 5, /** Octet String Eg. [0x01, 0x20] */ - ESP_MATTER_VAL_TYPE_OCTET_STRING, + ESP_MATTER_VAL_TYPE_OCTET_STRING = 6, /** 8 bit signed integer */ - ESP_MATTER_VAL_TYPE_INT8, + ESP_MATTER_VAL_TYPE_INT8 = 7, /** 8 bit unsigned integer */ - ESP_MATTER_VAL_TYPE_UINT8, + ESP_MATTER_VAL_TYPE_UINT8 = 8, /** 16 bit signed integer */ - ESP_MATTER_VAL_TYPE_INT16, + ESP_MATTER_VAL_TYPE_INT16 = 9, /** 16 bit unsigned integer */ - ESP_MATTER_VAL_TYPE_UINT16, + ESP_MATTER_VAL_TYPE_UINT16 = 10, + /** 32 bit signed integer */ + ESP_MATTER_VAL_TYPE_INT32 = 11, /** 32 bit unsigned integer */ - ESP_MATTER_VAL_TYPE_UINT32, + ESP_MATTER_VAL_TYPE_UINT32 = 12, + /** 64 bit signed integer */ + ESP_MATTER_VAL_TYPE_INT64 = 13, /** 64 bit unsigned integer */ - ESP_MATTER_VAL_TYPE_UINT64, + ESP_MATTER_VAL_TYPE_UINT64 = 14, /** 8 bit enum */ - ESP_MATTER_VAL_TYPE_ENUM8, + ESP_MATTER_VAL_TYPE_ENUM8 = 15, /** 8 bit bitmap */ - ESP_MATTER_VAL_TYPE_BITMAP8, + ESP_MATTER_VAL_TYPE_BITMAP8 = 16, /** 16 bit bitmap */ - ESP_MATTER_VAL_TYPE_BITMAP16, + ESP_MATTER_VAL_TYPE_BITMAP16 = 17, /** 32 bit bitmap */ - ESP_MATTER_VAL_TYPE_BITMAP32, + ESP_MATTER_VAL_TYPE_BITMAP32 = 18, + /** nullable types **/ + ESP_MATTER_VAL_TYPE_NULLABLE_INTEGER = ESP_MATTER_VAL_TYPE_INTEGER + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_FLOAT = ESP_MATTER_VAL_TYPE_FLOAT + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_INT8 = ESP_MATTER_VAL_TYPE_INT8 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_UINT8 = ESP_MATTER_VAL_TYPE_UINT8 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_INT16 = ESP_MATTER_VAL_TYPE_INT16 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_UINT16 = ESP_MATTER_VAL_TYPE_UINT16 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_INT32 = ESP_MATTER_VAL_TYPE_INT32 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_UINT32 = ESP_MATTER_VAL_TYPE_UINT32 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_INT64 = ESP_MATTER_VAL_TYPE_INT64 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_UINT64 = ESP_MATTER_VAL_TYPE_UINT64 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_ENUM8 = ESP_MATTER_VAL_TYPE_ENUM8 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP8 = ESP_MATTER_VAL_TYPE_BITMAP8 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP16 = ESP_MATTER_VAL_TYPE_BITMAP16 + ESP_MATTER_VAL_NULLANLE_BASE, + ESP_MATTER_VAL_TYPE_NULLABLE_BITMAP32= ESP_MATTER_VAL_TYPE_BITMAP32 + ESP_MATTER_VAL_NULLANLE_BASE, } esp_matter_val_type_t; /** ESP Matter Value */ @@ -87,8 +111,12 @@ typedef union { int16_t i16; /** 16 bit unsigned integer */ uint16_t u16; + /** 32 bit signed integer */ + int32_t i32; /** 32 bit unsigned integer */ uint32_t u32; + /** 64 bit signed integer */ + int64_t i64; /** 64 bit unsigned integer */ uint64_t u64; /** Array */ @@ -123,48 +151,110 @@ typedef struct esp_matter_attr_bounds { /** TODO: Step Value might be needed here later */ } esp_matter_attr_bounds_t; +template +class nullable { +public: + nullable(T value) + { + assert(!chip::app::NumericAttributeTraits::IsNullValue(value)); + val = value; + } + nullable() + { + chip::app::NumericAttributeTraits::SetNull(val); + } + + T value() + { + assert(!is_null()); + return val; + } + + T value_or(T ret) + { + return is_null() ? ret : val; + } + + bool is_null() + { + return chip::app::NumericAttributeTraits::IsNullValue(val); + } + + void operator=(T value) + { + assert(!chip::app::NumericAttributeTraits::IsNullValue(value)); + this->val = value; + } + + void operator=(std::nullptr_t) + { + chip::app::NumericAttributeTraits::SetNull(this->val); + } +private: + T val; +}; + /*** Attribute val APIs ***/ /** Invalid */ esp_matter_attr_val_t esp_matter_invalid(void *val); - /** Boolean */ esp_matter_attr_val_t esp_matter_bool(bool val); /** Integer */ esp_matter_attr_val_t esp_matter_int(int val); +esp_matter_attr_val_t esp_matter_nullable_int(nullable val); /** Float */ esp_matter_attr_val_t esp_matter_float(float val); +esp_matter_attr_val_t esp_matter_nullable_float(nullable val); /** 8 bit integer */ esp_matter_attr_val_t esp_matter_int8(int8_t val); +esp_matter_attr_val_t esp_matter_nullable_int8(nullable val); /** 8 bit unsigned integer */ esp_matter_attr_val_t esp_matter_uint8(uint8_t val); +esp_matter_attr_val_t esp_matter_nullable_uint8(nullable val); /** 16 bit signed integer */ esp_matter_attr_val_t esp_matter_int16(int16_t val); +esp_matter_attr_val_t esp_matter_nullable_int16(nullable val); /** 16 bit unsigned integer */ esp_matter_attr_val_t esp_matter_uint16(uint16_t val); +esp_matter_attr_val_t esp_matter_nullable_uint16(nullable val); + +/** 32 bit signed integer */ +esp_matter_attr_val_t esp_matter_int32(int32_t val); +esp_matter_attr_val_t esp_matter_nullable_int32(nullable val); /** 32 bit unsigned integer */ esp_matter_attr_val_t esp_matter_uint32(uint32_t val); +esp_matter_attr_val_t esp_matter_nullable_uint32(nullable val); + +/** 64 bit signed integer */ +esp_matter_attr_val_t esp_matter_int64(int64_t val); +esp_matter_attr_val_t esp_matter_nullable_int64(nullable val); /** 64 bit unsigned integer */ esp_matter_attr_val_t esp_matter_uint64(uint64_t val); +esp_matter_attr_val_t esp_matter_nullable_uint64(nullable val); /** 8 bit enum */ esp_matter_attr_val_t esp_matter_enum8(uint8_t val); +esp_matter_attr_val_t esp_matter_nullable_enum8(nullable val); /** 8 bit bitmap */ esp_matter_attr_val_t esp_matter_bitmap8(uint8_t val); +esp_matter_attr_val_t esp_matter_nullable_bitmap8(nullable val); /** 16 bit bitmap */ esp_matter_attr_val_t esp_matter_bitmap16(uint16_t val); +esp_matter_attr_val_t esp_matter_nullable_bitmap16(nullable val); /** 32 bit bitmap */ esp_matter_attr_val_t esp_matter_bitmap32(uint32_t val); +esp_matter_attr_val_t esp_matter_nullable_bitmap32(nullable val); /** Character string */ esp_matter_attr_val_t esp_matter_char_str(char *val, uint16_t data_size); @@ -176,6 +266,7 @@ esp_matter_attr_val_t esp_matter_octet_str(uint8_t *val, uint16_t data_size); esp_matter_attr_val_t esp_matter_array(uint8_t *val, uint16_t data_size, uint16_t count); namespace esp_matter { + namespace attribute { /** Attribute update callback type */ diff --git a/components/esp_matter/esp_matter_cluster.cpp b/components/esp_matter/esp_matter_cluster.cpp index 65062ec71..c0cd7609e 100644 --- a/components/esp_matter/esp_matter_cluster.cpp +++ b/components/esp_matter/esp_matter_cluster.cpp @@ -249,7 +249,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) if (flags & CLUSTER_FLAG_SERVER) { /* Attributes managed internally */ global::attribute::create_feature_map(cluster, 0); - + /* Attributes not managed internally */ if (config) { global::attribute::create_cluster_revision(cluster, config->cluster_revision); @@ -391,9 +391,9 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) attribute::create_scan_max_time_seconds(cluster, 0); attribute::create_connect_max_time_seconds(cluster, 0); attribute::create_interface_enabled(cluster, 0); - attribute::create_last_networking_status(cluster, 0); + attribute::create_last_networking_status(cluster, nullable()); attribute::create_last_network_id(cluster, NULL, 0); - attribute::create_last_connect_error_value(cluster, 0); + attribute::create_last_connect_error_value(cluster, nullable()); global::attribute::create_feature_map(cluster, 0); /* Attributes not managed internally */ @@ -631,10 +631,10 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) /* Attributes managed internally */ global::attribute::create_feature_map(cluster, 0); attribute::create_bssid(cluster, NULL, 0); - attribute::create_security_type(cluster, 0); - attribute::create_wifi_version(cluster, 0); - attribute::create_channel_number(cluster, 0); - attribute::create_rssi(cluster, 0); + attribute::create_security_type(cluster, nullable()); + attribute::create_wifi_version(cluster, nullable()); + attribute::create_channel_number(cluster, nullable()); + attribute::create_rssi(cluster, nullable()); /* Attributes not managed internally */ if (config) { @@ -672,19 +672,19 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags) if (flags & CLUSTER_FLAG_SERVER) { /* Attributes managed internally */ global::attribute::create_feature_map(cluster, 0); - attribute::create_channel(cluster, 0); - attribute::create_routing_role(cluster, 0); + attribute::create_channel(cluster, nullable(0)); + attribute::create_routing_role(cluster, nullable(0)); attribute::create_network_name(cluster, NULL, 0); - attribute::create_pan_id(cluster, 0); - attribute::create_extended_pan_id(cluster, 0); + attribute::create_pan_id(cluster, nullable(0)); + attribute::create_extended_pan_id(cluster, nullable(0)); attribute::create_mesh_local_prefix(cluster, NULL, 0); attribute::create_neighbor_table(cluster, NULL, 0, 0); attribute::create_route_table(cluster, NULL, 0, 0); - attribute::create_extended_partition_id(cluster, 0); - attribute::create_weighting(cluster, 0); - attribute::create_data_version(cluster, 0); - attribute::create_stable_data_version(cluster, 0); - attribute::create_leader_router_id(cluster, 0); + attribute::create_extended_partition_id(cluster, nullable(0)); + attribute::create_weighting(cluster, nullable(0)); + attribute::create_data_version(cluster, nullable(0)); + attribute::create_stable_data_version(cluster, nullable(0)); + attribute::create_leader_router_id(cluster, nullable(0)); attribute::create_security_policy(cluster, NULL, 0, 0); attribute::create_channel_page0_mask(cluster, NULL, 0); attribute::create_operational_dataset_components(cluster, NULL, 0, 0); @@ -1017,10 +1017,10 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_ /* Attributes managed internally */ attribute::create_remaining_time(cluster, 0); - for (uint8_t idx = 1; idx <= config->number_of_primaries; ++idx) { + for (uint8_t idx = 1; idx <= config->number_of_primaries.value_or(0); ++idx) { attribute::create_primary_n_x(cluster, 0, idx); attribute::create_primary_n_y(cluster, 0, idx); - attribute::create_primary_n_intensity(cluster, 0, idx); + attribute::create_primary_n_intensity(cluster, nullable(), idx); } } diff --git a/components/esp_matter/esp_matter_cluster.h b/components/esp_matter/esp_matter_cluster.h index c6f4c708f..bbce37ade 100644 --- a/components/esp_matter/esp_matter_cluster.h +++ b/components/esp_matter/esp_matter_cluster.h @@ -81,7 +81,7 @@ typedef struct config { uint16_t cluster_revision; bool update_possible; uint8_t update_state; - uint8_t update_state_progress; + nullable update_state_progress; config() : cluster_revision(1), update_possible(1), update_state(0), update_state_progress(0) {} } config_t; @@ -206,8 +206,8 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags, uint32_ namespace level_control { typedef struct config { uint16_t cluster_revision; - uint8_t current_level; - uint8_t on_level; + nullable current_level; + nullable on_level; uint8_t options; feature::lighting::config_t lighting; config() : cluster_revision(5), current_level(0), on_level(1), options(0) {} @@ -223,7 +223,7 @@ typedef struct config { uint8_t color_control_options; uint8_t enhanced_color_mode; uint16_t color_capabilities; - uint8_t number_of_primaries; + nullable number_of_primaries; feature::hue_saturation::config_t hue_saturation; feature::color_temperature::config_t color_temperature; feature::xy::config_t xy; @@ -241,10 +241,8 @@ typedef struct config { uint16_t cluster_revision; uint8_t fan_mode; uint8_t fan_mode_sequence; - /* Not implemented - uint8_t percent_setting; + nullable percent_setting; uint8_t percent_current; - */ config() : cluster_revision(2), fan_mode(5), fan_mode_sequence(2) {} } config_t; @@ -254,12 +252,12 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); namespace thermostat { typedef struct config { uint16_t cluster_revision; - int16_t local_temperature; + nullable local_temperature; int16_t occupied_cooling_setpoint; int16_t occupied_heating_setpoint; uint8_t control_sequence_of_operation; uint8_t system_mode; - config() : cluster_revision(5), local_temperature(0), occupied_cooling_setpoint(0x0A28), + config() : cluster_revision(5), local_temperature(), occupied_cooling_setpoint(0x0A28), occupied_heating_setpoint(0x07D0), control_sequence_of_operation(4), system_mode(1) {} } config_t; @@ -269,7 +267,7 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); namespace door_lock { typedef struct config { uint16_t cluster_revision; - uint8_t lock_state; + nullable lock_state; uint8_t lock_type; bool actuator_enabled; uint32_t auto_relock_time; @@ -326,10 +324,10 @@ cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); namespace temperature_measurement { typedef struct config { uint16_t cluster_revision; - int16_t measured_value; - int16_t min_measured_value; - int16_t max_measured_value; - config() : cluster_revision(4), measured_value(-32768), min_measured_value(-32768), max_measured_value(-32768) {} + nullable measured_value; + nullable min_measured_value; + nullable max_measured_value; + config() : cluster_revision(4), measured_value(), min_measured_value(), max_measured_value() {} } config_t; cluster_t *create(endpoint_t *endpoint, config_t *config, uint8_t flags); diff --git a/components/esp_matter/esp_matter_feature.h b/components/esp_matter/esp_matter_feature.h index dbb5b339a..23fea793d 100644 --- a/components/esp_matter/esp_matter_feature.h +++ b/components/esp_matter/esp_matter_feature.h @@ -37,9 +37,9 @@ namespace lighting { typedef struct config { bool global_scene_control; - uint16_t on_time; - uint16_t off_wait_time; - uint8_t start_up_on_off; + nullable on_time; + nullable off_wait_time; + nullable start_up_on_off; config() : global_scene_control(1), on_time(0), off_wait_time(0), start_up_on_off(0) {} } config_t; @@ -65,7 +65,7 @@ typedef struct config { uint16_t remaining_time; uint8_t min_level; uint8_t max_level; - uint8_t start_up_current_level; + nullable start_up_current_level; config() : remaining_time(0), min_level(1), max_level(254), start_up_current_level(0) {} } config_t; @@ -111,8 +111,8 @@ typedef struct config { uint16_t color_temp_physical_min_mireds; uint16_t color_temp_physical_max_mireds; uint16_t couple_color_temp_to_level_min_mireds; - uint16_t startup_color_temperature_mireds; - config() : color_temperature_mireds(0x00fa), color_temp_physical_min_mireds(1), + nullable startup_color_temperature_mireds; + config() : color_temperature_mireds(0x00fa), color_temp_physical_min_mireds(0), color_temp_physical_max_mireds(0xfeff), couple_color_temp_to_level_min_mireds(0), startup_color_temperature_mireds(0x00fa) {} } config_t;