diff --git a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts index 15eb5413cb..339469d26c 100644 --- a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts +++ b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts @@ -15863,5 +15863,5 @@ export let ClusterTypeAttrs: any = { commands: [ ] } - } + }, } diff --git a/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam b/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam index 233aaeaea1..c76421dead 100644 --- a/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam +++ b/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam @@ -54,6 +54,10 @@ def zb_ACLouverPosition 0x02010045 def zb_ACCoilTemperature 0x02010046 def zb_ACCapacityFormat 0x02010047 +// Unify thermostat cluster +def zb_ZWaveSystemMode 0xfd150001 +def zb_SupportedSystemMode 0xfd150002 + def thermostat_setpoint_supported (e'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE | e'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE) scope 0 { @@ -131,23 +135,48 @@ scope 0 { r'zb_SystemMode = - if (r'zwTHERMOSTAT_MODE == 0) 0 - if (r'zwTHERMOSTAT_MODE == 1) 4 - if (r'zwTHERMOSTAT_MODE == 2) 3 - if (r'zwTHERMOSTAT_MODE == 3) 1 - if (r'zwTHERMOSTAT_MODE == 6) 7 - if (r'zwTHERMOSTAT_MODE == 8) 8 + if (r'zwTHERMOSTAT_MODE == 0x00) 0x00 + if (r'zwTHERMOSTAT_MODE == 0x01) 0x04 + if (r'zwTHERMOSTAT_MODE == 0x02) 0x03 + if (r'zwTHERMOSTAT_MODE == 0x03) 0x01 + if (r'zwTHERMOSTAT_MODE == 0x04) 0x0A + if (r'zwTHERMOSTAT_MODE == 0x05) 0x0B + if (r'zwTHERMOSTAT_MODE == 0x06) 0x07 + if (r'zwTHERMOSTAT_MODE == 0x07) 0x0C + if (r'zwTHERMOSTAT_MODE == 0x08) 0x08 + if (r'zwTHERMOSTAT_MODE == 0x09) 0x0D + if (r'zwTHERMOSTAT_MODE == 0x0A) 0x0E + if (r'zwTHERMOSTAT_MODE == 0x0B) 0x0F + if (r'zwTHERMOSTAT_MODE == 0x0C) 0x10 + if (r'zwTHERMOSTAT_MODE == 0x0D) 0x11 + if (r'zwTHERMOSTAT_MODE == 0x0F) 0x12 + if (r'zwTHERMOSTAT_MODE == 0x1F) 0x13 undefined - d'zwTHERMOSTAT_MODE = - if ( d'zb_SystemMode == 0) 0 - if ( d'zb_SystemMode == 4) 1 - if ( d'zb_SystemMode == 3) 2 - if ( d'zb_SystemMode == 1) 3 - if ( d'zb_SystemMode == 7) 6 - if ( d'zb_SystemMode == 8) 8 + r'zwTHERMOSTAT_MODE = + if (r'zb_SystemMode == 0x00) 0x00 + if (r'zb_SystemMode == 0x04) 0x01 + if (r'zb_SystemMode == 0x03) 0x02 + if (r'zb_SystemMode == 0x01) 0x03 + if (r'zb_SystemMode == 0x0A) 0x04 + if (r'zb_SystemMode == 0x0B) 0x05 + if (r'zb_SystemMode == 0x07) 0x06 + if (r'zb_SystemMode == 0x0C) 0x07 + if (r'zb_SystemMode == 0x08) 0x08 + if (r'zb_SystemMode == 0x0D) 0x09 + if (r'zb_SystemMode == 0x0E) 0x0A + if (r'zb_SystemMode == 0x0F) 0x0B + if (r'zb_SystemMode == 0x10) 0x0C + if (r'zb_SystemMode == 0x11) 0x0D + if (r'zb_SystemMode == 0x12) 0x0F + if (r'zb_SystemMode == 0x13) 0x1F undefined + // Unify cluster is 1on 1 mapping + r'zb_ZWaveSystemMode = r'zwTHERMOSTAT_MODE + r'zwTHERMOSTAT_MODE = r'zb_ZWaveSystemMode + + r'zb_ControlSequenceOfOperation = if(((r'zwTHERMOSTAT_SUPPORTED_MODES) & 6) == 0x06) 0x04 if(((r'zwTHERMOSTAT_SUPPORTED_MODES) & 6) == 0x02) 0x02 @@ -252,4 +281,7 @@ scope 0 chain_reaction(0) { d'zb_ACCapacityFormat = if (r'zb_ACCapacityFormat != d'zb_ACCapacityFormat) r'zb_ACCapacityFormat undefined + + + r'zb_SupportedSystemMode = r'zwTHERMOSTAT_SUPPORTED_MODES } diff --git a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp index 774ba2882d..003b88b396 100644 --- a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp +++ b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp @@ -289,7 +289,7 @@ static const std::vector attribute_schema = { ///////////////////////////////////////////////////////////////////// {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_MODE_VERSION, "Thermostat Mode Version", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_MODE, "Thermostat Mode", ATTRIBUTE_ENDPOINT_ID, I32_STORAGE_TYPE}, - {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SUPPORTED_MODES, "Thermostat Supported Modes", ATTRIBUTE_ENDPOINT_ID, BYTE_ARRAY_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SUPPORTED_MODES, "Thermostat Supported Modes", ATTRIBUTE_ENDPOINT_ID, U32_STORAGE_TYPE}, ///////////////////////////////////////////////////////////////////// // Thermostat Setpoint Command Class attributes ///////////////////////////////////////////////////////////////////// diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_mode.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_mode.c index 8b43de168c..8de55e3fa3 100644 --- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_mode.c +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_mode.c @@ -189,12 +189,23 @@ static sl_status_t zwave_command_class_thermostat_mode_handle_supported_report( uint8_t bitmask_length = frame_length - THERMOSTAT_MODE_SUPPORTED_REPORT_BITMASK_INDEX; + uint32_t supported_thermostat_bitmask = 0x0000; - attribute_store_set_node_attribute_value( - supported_modes_node, - REPORTED_ATTRIBUTE, - &frame_data[THERMOSTAT_MODE_SUPPORTED_REPORT_BITMASK_INDEX], - bitmask_length); + // Since we are using uint32_t we can't have more that 4 bit mask + if (bitmask_length > 4) { + sl_log_error(LOG_TAG, + "Supported Thermostat Mode type Bit Mask length is not supported\n"); + return SL_STATUS_NOT_SUPPORTED; + } + + for (int i = bitmask_length; i > 0; i--) { + supported_thermostat_bitmask + = (supported_thermostat_bitmask << 8) | frame_data[1 + i]; + } + + attribute_store_set_reported(supported_modes_node, + &supported_thermostat_bitmask, + sizeof(supported_thermostat_bitmask)); return SL_STATUS_OK; } diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_thermostat_mode_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_thermostat_mode_test.c index 136644e500..81408beb85 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_thermostat_mode_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_thermostat_mode_test.c @@ -371,13 +371,14 @@ void test_thermostat_mode_incoming_supported_report_happy_case() ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SUPPORTED_MODES, endpoint_id_node); + uint8_t bit1 = 0b0000101; + uint8_t bit2 = 0b0000011; + uint8_t bit3 = 0b1111111; const uint8_t incoming_report_frame[] = {COMMAND_CLASS_THERMOSTAT_MODE_V3, THERMOSTAT_MODE_SUPPORTED_REPORT_V3, - 1, - 3, - 4, - 5, - 6}; + bit1, + bit2, + bit3}; TEST_ASSERT_EQUAL( SL_STATUS_OK, @@ -385,17 +386,14 @@ void test_thermostat_mode_incoming_supported_report_happy_case() incoming_report_frame, sizeof(incoming_report_frame))); - uint8_t received_bitmask[20] = {}; - uint8_t received_bitmask_length = 0; - attribute_store_get_node_attribute_value(supported_modes_node, - REPORTED_ATTRIBUTE, - received_bitmask, - &received_bitmask_length); - - TEST_ASSERT_EQUAL(5, received_bitmask_length); - TEST_ASSERT_EQUAL_UINT8_ARRAY(&incoming_report_frame[2], - received_bitmask, - received_bitmask_length); + uint32_t received_bitmask = 0; + attribute_store_get_reported(supported_modes_node, + &received_bitmask, + sizeof(received_bitmask)); + + TEST_ASSERT_EQUAL_MESSAGE((bit3) << 16 | (bit2) << 8 | bit1, + received_bitmask, + "Received Bitmask mismatch"); } void test_thermostat_mode_incoming_supported_report_too_short() diff --git a/components/uic_dotdot/dotdot-xml/Unify_Thermostat.xml b/components/uic_dotdot/dotdot-xml/Unify_Thermostat.xml new file mode 100644 index 0000000000..fffa052345 --- /dev/null +++ b/components/uic_dotdot/dotdot-xml/Unify_Thermostat.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/uic_dotdot/dotdot-xml/library.xml b/components/uic_dotdot/dotdot-xml/library.xml index 78c9d8140a..41096c633f 100644 --- a/components/uic_dotdot/dotdot-xml/library.xml +++ b/components/uic_dotdot/dotdot-xml/library.xml @@ -490,5 +490,5 @@ applicable to this document can be found in the LICENSE.md file. - + diff --git a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h index 70c0a280c2..bb5af1c1f5 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h @@ -856,6 +856,9 @@ typedef enum { #define DOTDOT_PROTOCOL_CONTROLLER_NETWORK_MANAGEMENT_NETWORK_MANAGEMENT_STATE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1) // Definitions for cluster: Descriptor #define DOTDOT_DESCRIPTOR_DEVICE_TYPE_LIST_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x0) +// Definitions for cluster: UnifyThermostat +#define DOTDOT_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1) +#define DOTDOT_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x2) // clang-format on diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h index 2833fd9544..a553279a68 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h @@ -364,6 +364,8 @@ // Commands for cluster: Descriptor +// Commands for cluster: UnifyThermostat + #ifdef __cplusplus extern "C" { #endif diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h index 1878448a59..12890d4ec4 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h @@ -254,6 +254,10 @@ #define DOTDOT_DESCRIPTOR_CLUSTER_ID ((dotdot_cluster_id_t)0xFD13) +// Definitions for cluster: UnifyThermostat +#define DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID ((dotdot_cluster_id_t)0xFD15) + + #ifdef __cplusplus extern "C" { #endif diff --git a/components/uic_dotdot/zap-generated/include/zap-types.h b/components/uic_dotdot/zap-generated/include/zap-types.h index fb82f117ca..f6dede95b2 100644 --- a/components/uic_dotdot/zap-generated/include/zap-types.h +++ b/components/uic_dotdot/zap-generated/include/zap-types.h @@ -1271,6 +1271,26 @@ typedef enum { ZCL_TX_REPORT_TRANSMISSION_SPEED_UNKNOWN = 255, } TxReportTransmissionSpeed; +// Enum for UnifyThermostatThermostatMode +typedef enum { + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_OFF = 0, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_HEAT = 1, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_COOL = 2, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_AUTO = 3, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_AUXILIARY = 4, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_RESUME = 5, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_FAN = 6, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_FURNACE = 7, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_DRY = 8, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_MOIST = 9, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_AUTO_CHANGEOVER = 10, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENERGY_HEAT = 11, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENERGY_COOL = 12, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_AWAY = 13, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_FULL_POWER = 15, + ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC = 31, +} UnifyThermostatThermostatMode; + // Enum for WindowCoveringWindowCoveringType typedef enum { ZCL_WINDOW_COVERING_WINDOW_COVERING_TYPE_ROLLERSHADE = 0, @@ -1954,6 +1974,38 @@ typedef enum { #define TSTAT_SCHEDULE_MODE_HEAT_OFFSET (0) #define TSTAT_SCHEDULE_MODE_COOL (2) #define TSTAT_SCHEDULE_MODE_COOL_OFFSET (1) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_OFF (1) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_OFF_OFFSET (0) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_HEAT (2) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_HEAT_OFFSET (1) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_COOL (4) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_COOL_OFFSET (2) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUTO (8) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUTO_OFFSET (3) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUXILIARY (16) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUXILIARY_OFFSET (4) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_RESUME (32) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_RESUME_OFFSET (5) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FAN (64) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FAN_OFFSET (6) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FURNACE (128) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FURNACE_OFFSET (7) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_DRY (256) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_DRY_OFFSET (8) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MOIST (512) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MOIST_OFFSET (9) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUTO_CHANGEOVER (1024) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AUTO_CHANGEOVER_OFFSET (10) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENERGY_HEAT (2048) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENERGY_HEAT_OFFSET (11) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENERGY_COOL (4096) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENERGY_COOL_OFFSET (12) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AWAY (8192) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_AWAY_OFFSET (13) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FULL_POWER (16384) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FULL_POWER_OFFSET (14) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC (32768) +#define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC_OFFSET (15) #define WINDOW_COVERING_CONFIG_OR_STATUS_OPERATIONAL (1) #define WINDOW_COVERING_CONFIG_OR_STATUS_OPERATIONAL_OFFSET (0) #define WINDOW_COVERING_CONFIG_OR_STATUS_ONLINE (2) diff --git a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md index dbdfa36ecb..103193ffb9 100644 --- a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md +++ b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md @@ -53949,6 +53949,318 @@ mosquitto_pub -t 'ucl/by-unid///Descriptor/Commands/ForceReadAttribute +


+ + + + + + + +\page unify_thermostat UnifyThermostat Cluster +The following commands and attributes are accepted as JSON payloads for the +UnifyThermostat cluster. + +

+ + + + +\section unify_thermostat_attrs UnifyThermostat Attributes +The following attribute topics are used to retrieve the UnifyThermostat cluster state. + +
+ +\subsection unify_thermostat_attr_thermostat_mode UnifyThermostat/ThermostatMode Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/Attributes/ThermostatMode/Reported +[PREFIX]/UnifyThermostat/Attributes/ThermostatMode/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Cluster ThermostatMode Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "UnifyThermostatThermostatMode" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for ThermostatMode attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UnifyThermostat/Attributes/ThermostatMode/+' + +# Example output + +ucl/by-unid//ep0/UnifyThermostat/Attributes/ThermostatMode/Desired { "value": } +ucl/by-unid//ep0/UnifyThermostat/Attributes/ThermostatMode/Reported { "value": } + +``` + +

+ +\subsection unify_thermostat_attr_supported_thermostat_mode UnifyThermostat/SupportedThermostatMode Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/Attributes/SupportedThermostatMode/Reported +[PREFIX]/UnifyThermostat/Attributes/SupportedThermostatMode/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Cluster SupportedThermostatMode Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "UnifyThermostatSupportedThermostatMode" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportedThermostatMode attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UnifyThermostat/Attributes/SupportedThermostatMode/+' + +# Example output + +ucl/by-unid//ep0/UnifyThermostat/Attributes/SupportedThermostatMode/Desired { "value": } +ucl/by-unid//ep0/UnifyThermostat/Attributes/SupportedThermostatMode/Reported { "value": } + +``` + +

+ + +\subsection unify_thermostat_attr_cluster_revision UnifyThermostat/ClusterRevision Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/Attributes/ClusterRevision/Reported +[PREFIX]/UnifyThermostat/Attributes/ClusterRevision/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Cluster ClusterRevision Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "integer" + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for ClusterRevision attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UnifyThermostat/Attributes/ClusterRevision/+' +# Example output +ucl/by-unid///UnifyThermostat/Attributes/ClusterRevision/Desired { "value": } +ucl/by-unid///UnifyThermostat/Attributes/ClusterRevision/Reported { "value": } +``` + + + + + +

+ + + + +\section unify_thermostat_recv_cmd_support UnifyThermostat Command Support + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/SupportedCommands +[PREFIX]/UnifyThermostat/SupportedGeneratedCommands +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Command Support Properties", + "type": "object", + "properties": { + "value": { + "type": "array", + "items" : { + "type": "string", + "enum": [ + ] + } + } + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To see supported commands for UnifyThermostat cluster under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UnifyThermostat/SupportedCommands' +# Example output +ucl/by-unid///UnifyThermostat/SupportedCommands { "value": [] } +``` + +To see supported generated commands for UnifyThermostat cluster under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UnifyThermostat/SupportedGeneratedCommands' +# Example output +ucl/by-unid///UnifyThermostat/SupportedGeneratedCommands { "value": [] } +``` + + + + + +

+ + + + +\section unify_thermostat_cmds UnifyThermostat Commands + +

+ +\subsection unify_thermostat_write_attr_cmd UnifyThermostat/WriteAttributes Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/Commands/WriteAttributes +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Cluster WriteAttributes Command Properties", + "type": "object", + "properties": { + "ThermostatMode": { + "type": "UnifyThermostatThermostatMode" + }, + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To update all UnifyThermostat attributes under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UnifyThermostat/Commands/WriteAttributes' -m '{ "ThermostatMode": , }' +``` + +> NOTE: Specify only the list of attributes to write in this command. +> Unspecified attributes will not be updated. + +

+ +\subsection unify_thermostat_force_read_attr_cmd UnifyThermostat/ForceReadAttributes Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UnifyThermostat/Commands/ForceReadAttributes +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostat Cluster ForceReadAttributes Command Properties", + "type": "object", + "properties": { + "value": { + "type": "array" + "items": { + "type": "string", + "enum": [ + "ThermostatMode", + "SupportedThermostatMode" + ] + } + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To force read all UnifyThermostat attributes under the by-unid topic space (by sending an empty array): + +```console +mosquitto_pub -t 'ucl/by-unid///UnifyThermostat/Commands/ForceReadAttributes' -m '{ "value": [] }' +``` + +To force read one of the UnifyThermostat attributes under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UnifyThermostat/Commands/ForceReadAttributes' -m '{ "value": ["ThermostatMode"] }' +``` + + + + +


@@ -57545,6 +57857,43 @@ mosquitto_pub -t 'ucl/by-unid///Descriptor/Commands/ForceReadAttribute

+ + + +\section enum_unify_thermostat_thermostat_mode UnifyThermostatThermostatMode Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostatThermostatMode Enum Properties", + "type": "string", + "enum": [ + "Off", + "Heat", + "Cool", + "Auto", + "Auxiliary", + "Resume", + "Fan", + "Furnace", + "Dry", + "Moist", + "AutoChangeover", + "EnergyHeat", + "EnergyCool", + "Away", + "FullPower", + "ManufacturerSpecific" + ] +} +``` + + + + + +

+ @@ -59947,6 +60296,75 @@ mosquitto_pub -t 'ucl/by-unid///Descriptor/Commands/ForceReadAttribute

+ + + +\section enum_unify_thermostat_supported_thermostat_mode UnifyThermostatSupportedThermostatMode Bitmap + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UnifyThermostatSupportedThermostatMode Enum Properties", + "type": "object", + "properties": { + "Off": { + "type": "boolean" + }, + "Heat": { + "type": "boolean" + }, + "Cool": { + "type": "boolean" + }, + "Auto": { + "type": "boolean" + }, + "Auxiliary": { + "type": "boolean" + }, + "Resume": { + "type": "boolean" + }, + "Fan": { + "type": "boolean" + }, + "Furnace": { + "type": "boolean" + }, + "Dry": { + "type": "boolean" + }, + "Moist": { + "type": "boolean" + }, + "AutoChangeover": { + "type": "boolean" + }, + "EnergyHeat": { + "type": "boolean" + }, + "EnergyCool": { + "type": "boolean" + }, + "Away": { + "type": "boolean" + }, + "FullPower": { + "type": "boolean" + }, + "ManufacturerSpecific": { + "type": "boolean" + } + } +} +``` + + + + + +

+ diff --git a/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c b/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c index cd3e175e69..669a7e948c 100644 --- a/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c +++ b/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c @@ -2025,6 +2025,19 @@ const char *uic_dotdot_get_attribute_name(dotdot_cluster_id_t cluster_id, return "Unknown"; } // clang-format off + case DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID: + // clang-format on + switch (attribute_id) { + // clang-format off + case DOTDOT_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ATTRIBUTE_ID: + return "ThermostatMode"; + case DOTDOT_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ATTRIBUTE_ID: + return "SupportedThermostatMode"; + // clang-format on + default: + return "Unknown"; + } + // clang-format off // clang-format on default: return "Unknown"; @@ -4409,6 +4422,14 @@ dotdot_attribute_id_t return DOTDOT_DESCRIPTOR_DEVICE_TYPE_LIST_ATTRIBUTE_ID; } break; + case DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID: + if (strcmp ("ThermostatMode", attribute_name) == 0) { + return DOTDOT_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ATTRIBUTE_ID; + } + if (strcmp ("SupportedThermostatMode", attribute_name) == 0) { + return DOTDOT_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ATTRIBUTE_ID; + } + break; default: return DOTDOT_INVALID_ATTRIBUTE_ID; } @@ -6426,6 +6447,19 @@ dotdot_attribute_json_type_t return JSON_TYPE_UNKNOWN; } // clang-format off + case DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID: + // clang-format on + switch (attribute_id) { + // clang-format off + case DOTDOT_UNIFY_THERMOSTAT_THERMOSTAT_MODE_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + case DOTDOT_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + // clang-format on + default: + return JSON_TYPE_UNKNOWN; + } + // clang-format off // clang-format on default: return JSON_TYPE_UNKNOWN; @@ -6774,5 +6808,11 @@ bool uic_dotdot_attribute_is_enum(dotdot_cluster_id_t cluster_id, if (64787 == cluster_id) { } + if (64789 == cluster_id) { + if (1 == attribute_id) { + return true; + } + } + return false; } diff --git a/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c b/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c index 18b5402fa7..dd4cb03a04 100644 --- a/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c +++ b/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c @@ -128,6 +128,8 @@ const char* uic_dotdot_get_cluster_name(dotdot_cluster_id_t cluster_id) { return "ProtocolController-NetworkManagement"; case DOTDOT_DESCRIPTOR_CLUSTER_ID: return "Descriptor"; + case DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID: + return "UnifyThermostat"; default: return "Unknown"; } @@ -299,6 +301,9 @@ dotdot_cluster_id_t uic_dotdot_get_cluster_id(const char* cluster_name) { if (strcmp ("Descriptor", cluster_name) == 0) { return DOTDOT_DESCRIPTOR_CLUSTER_ID; } + if (strcmp ("UnifyThermostat", cluster_name) == 0) { + return DOTDOT_UNIFY_THERMOSTAT_CLUSTER_ID; + } // Return an invalid ID if we did not get any match. return DOTDOT_INVALID_CLUSTER_ID; diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h index f0dc62b095..40b62a2b66 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h @@ -40444,6 +40444,189 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( void uic_mqtt_dotdot_descriptor_publish_empty_supported_commands( const dotdot_unid_t unid ,dotdot_endpoint_id_t endpoint); +// Callback types used by the unify_thermostat cluster + +typedef struct { + uint8_t thermostat_mode; + uint16_t supported_thermostat_mode; +} uic_mqtt_dotdot_unify_thermostat_state_t; + +typedef struct { + bool thermostat_mode; + bool supported_thermostat_mode; +} uic_mqtt_dotdot_unify_thermostat_updated_state_t; + +typedef sl_status_t (*uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t)( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_unify_thermostat_state_t, + uic_mqtt_dotdot_unify_thermostat_updated_state_t +); + +typedef sl_status_t (*uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t)( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_unify_thermostat_updated_state_t +); + + + + +/** + * @brief Setup a callback for WriteAttribute to be called when a + * +/unify_thermostat/Commands/WriteAttributes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback +); +/** + * @brief Unsets a callback for WriteAttribute to be called when a + * +/unify_thermostat/Commands/WriteAttributes is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_unset_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback +); +/** + * @brief Clears all callbacks registered for when + * +/unify_thermostat/Commands/WriteAttributes is received. + */ +void uic_mqtt_dotdot_clear_unify_thermostat_write_attributes_callbacks(); + +/** + * @brief Setup a callback for ForceReadAttributes to be called when a + * +/unify_thermostat/Commands/ForceReadAttributes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback +); +/** + * @brief Unsets a callback for ForceReadAttributes to be called when a + * +/unify_thermostat/Commands/ForceReadAttributes is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_unset_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback +); +/** + * @brief Clears all callbacks registered for when + * +/unify_thermostat/Commands/ForceReadAttributes is received. + */ +void uic_mqtt_dotdot_clear_unify_thermostat_force_read_attributes_callbacks(); + +/** + * @brief Publish the attribute; UnifyThermostat/Attributes/ThermostatMode + * + * @param base_topic topic prefix to publish, /thermostat_mode + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UnifyThermostat/Attributes/ThermostatMode + * + * @param base_topic topic prefix to publish, /thermostat_mode + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UnifyThermostat/Attributes/SupportedThermostatMode + * + * @param base_topic topic prefix to publish, /supported_thermostat_mode + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UnifyThermostat/Attributes/SupportedThermostatMode + * + * @param base_topic topic prefix to publish, /supported_thermostat_mode + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + + +/** + * @brief Publish the UnifyThermostat/ClusterRevision attribute + * + * @param base_topic topic prefix to publish, /UnifyThermostat/Attributes/ClusterRevision + * will be appended. + * @param value Value to publish. + */ +void uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value); + +/** + * @brief Unretain a publication to UnifyThermostat/ClusterRevision attribute + * + * @param base_topic topic prefix to publish, /UnifyThermostat/Attributes/ClusterRevision + * will be appended. + */ +void uic_mqtt_dotdot_unify_thermostat_unretain_cluster_revision(const char* base_topic); + +/** + * @brief Publish the SupportedCommands for UNID/EndPoint for the UnifyThermostat Cluster + * + * This function will iterate over all Commands in the UnifyThermostat Cluster and + * call all registered callback functions with UNID/endpoint, and + * callback_type = UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK. + * All Cluster Command callback functions that return SL_STATUS_OK + * will be added to the list of supported commands and published. + * + * @param unid + * @param endpoint + */ +void uic_mqtt_dotdot_unify_thermostat_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint); + +/** + * @brief Publish an empty array of SupportedCommands for UNID/EndPoint for + * the UnifyThermostat Cluster + * + * @param unid + * @param endpoint ) + */ +void uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands( + const dotdot_unid_t unid + ,dotdot_endpoint_id_t endpoint); /** * @brief Publish the SupportedCommands for UNID/EndPoint diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h index 92daf48a23..de3aa90ef5 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h @@ -5134,6 +5134,21 @@ typedef sl_status_t (*uic_mqtt_dotdot_descriptor_attribute_device_type_list_call size_t device_type_list_count, const DeviceTypeStruct* device_type_list ); +// Callback types used by the unify_thermostat cluster +typedef sl_status_t (*uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint8_t thermostat_mode +); +typedef sl_status_t (*uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint16_t supported_thermostat_mode +); #ifdef __cplusplus extern "C" { @@ -9858,6 +9873,26 @@ sl_status_t uic_mqtt_dotdot_descriptor_attributes_init(); void uic_mqtt_dotdot_descriptor_attribute_device_type_list_callback_set(const uic_mqtt_dotdot_descriptor_attribute_device_type_list_callback_t callback); +/** + * Initializes the attributes features for the UnifyThermostat cluster, + * allowing to receive attribute updates from other UNIDs. + */ +sl_status_t uic_mqtt_dotdot_unify_thermostat_attributes_init(); + +/** + * Setup callback to be called when a + * UnifyThermostat/Attributes/thermostat_mode/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_set(const uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_t callback); +/** + * Setup callback to be called when a + * UnifyThermostat/Attributes/supported_thermostat_mode/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_set(const uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_t callback); + + #ifdef __cplusplus } #endif // __cplusplus diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h index 16d97617d4..01bbaadead 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h @@ -4987,6 +4987,28 @@ void uic_mqtt_dotdot_descriptor_publish_generated_write_attributes_command( ); +/** + * @brief Publishes an incoming/generated WriteAttributes command for + * the UnifyThermostat cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UnifyThermostat/GeneratedCommands/WriteAttributes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * @param attribute_values Values to assign to the attributes + * @param attribute_list List of attributes that are written + */ +void uic_mqtt_dotdot_unify_thermostat_publish_generated_write_attributes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_unify_thermostat_state_t attribute_values, + uic_mqtt_dotdot_unify_thermostat_updated_state_t attribute_list +); + + #ifdef __cplusplus } #endif // __cplusplus diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h index a5c1d17ef9..c17a3b068d 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h @@ -3709,6 +3709,23 @@ void uic_mqtt_dotdot_by_group_descriptor_write_attributes_callback_set( +typedef void (*uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_t)( + const dotdot_group_id_t group_id, + uic_mqtt_dotdot_unify_thermostat_state_t, + uic_mqtt_dotdot_unify_thermostat_updated_state_t +); + +/** + * Setup a callback for WriteAttribute to be called when a + * ucl/by-group/+/unify_thermostat/Commands/WriteAttributes is received. + * Setting this callback will overwrite any previously set callback. + */ +void uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_set( + const uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_t callback +); + + + #ifdef __cplusplus } #endif // __cplusplus diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h index dcc29ad5f1..532564b30f 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h @@ -811,6 +811,13 @@ char *tx_report_transmission_speed_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size); /** Get tx_report_transmission_speed enum representation from string. */ uint32_t tx_report_transmission_speed_get_enum_value_number_c(const char *str); +#define UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE 1 + +/** Get unify_thermostat_thermostat_mode string representation from enum. */ +char *unify_thermostat_thermostat_mode_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get unify_thermostat_thermostat_mode enum representation from string. */ +uint32_t unify_thermostat_thermostat_mode_get_enum_value_number_c(const char *str); #define WINDOW_COVERING_WINDOW_COVERING_TYPE_ENUM_NAME_AVAILABLE 1 /** Get window_covering_window_covering_type string representation from enum. */ diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp index 8db91a511c..b5e5cdd7c6 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp @@ -1934,6 +1934,23 @@ std::string tx_report_transmission_speed_get_enum_value_name( */ uint32_t tx_report_transmission_speed_get_enum_value_number(const std::string &str); +#define UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the UnifyThermostatThermostatMode enum + * + * @returns A string representation of the value. + */ +std::string unify_thermostat_thermostat_mode_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the UnifyThermostatThermostatMode enum + * + * @returns A number enum value. + */ +uint32_t unify_thermostat_thermostat_mode_get_enum_value_number(const std::string &str); + #define WINDOW_COVERING_WINDOW_COVERING_TYPE_ENUM_NAME_AVAILABLE 1 /** diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h index 3180bd0498..af6b1f805b 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h @@ -1664,6 +1664,34 @@ void uic_mqtt_dotdot_descriptor_publish_supported_generated_commands( ); +/** + * @brief Struct containing the list of commands for UnifyThermostat + */ +typedef struct _uic_mqtt_dotdot_unify_thermostat_supported_commands_ { + bool write_attributes; +} uic_mqtt_dotdot_unify_thermostat_supported_commands_t; + +/** + * @brief Sends/Publishes a the SupportedGenerated commands for + * the UnifyThermostat cluster for a UNID/Endpoint + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UnifyThermostat/SupportedGeneratedCommands + * + * @param unid The UNID of the node on behalf of which the advertisment is made + * + * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made + * + * @param command_list Struct pointer with the fields value indicating if + * individual commands can be generated. + */ +void uic_mqtt_dotdot_unify_thermostat_publish_supported_generated_commands( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_unify_thermostat_supported_commands_t *command_list +); + + #ifdef __cplusplus } diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp index 5dbf0c607a..279299ba88 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp @@ -94739,6 +94739,340 @@ sl_status_t uic_mqtt_dotdot_descriptor_init() return SL_STATUS_OK; } +// Callbacks pointers +static std::set uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; +static std::set uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback; + +// Callbacks setters + +void uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unset_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_unify_thermostat_write_attributes_callbacks() +{ + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback() +{ + return uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; +} + +void uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unset_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_unify_thermostat_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.clear(); +} + + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyThermostat/Commands/WriteAttributes +void uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + if (uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { + return; + } + + if (message_length == 0) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_unify_thermostat_state_t new_state = {}; + uic_mqtt_dotdot_unify_thermostat_updated_state_t new_updated_state = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyThermostat", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", ""); + return; + } + + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); + } + +} + +static void uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) +{ + uint8_t endpoint = 0; + std::string unid; + + if ((message_length == 0) || (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty())) { + return; + } + + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + try { + uic_mqtt_dotdot_unify_thermostat_updated_state_t force_update = {0}; + bool trigger_handler = false; + + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); + + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.thermostat_mode = true; + force_update.supported_thermostat_mode = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"ThermostatMode", &force_update.thermostat_mode }, + {"SupportedThermostatMode", &force_update.supported_thermostat_mode }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } + } + + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } + } + } catch (...) { + sl_log_debug(LOG_TAG, "UnifyThermostat/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; + } +} + +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; + + // This is a single value + + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_thermostat_thermostat_mode_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_THERMOSTAT_THERMOSTAT_MODE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/ThermostatMode", e.what()); + return SL_STATUS_OK; + } + + + std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ThermostatMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; +} + +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) +{ + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/ThermostatMode"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; +} +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; + + // This is a single value + + nlohmann::json bitmap_values = UnifyThermostatSupportedThermostatMode.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/SupportedThermostatMode", e.what()); + return SL_STATUS_OK; + } + + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); + + std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/SupportedThermostatMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; +} + +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) +{ + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/SupportedThermostatMode"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; +} +// clang-format off + + +sl_status_t uic_mqtt_dotdot_unify_thermostat_init() +{ + std::string base_topic = "ucl/by-unid/+/+/"; + + std::string subscription_topic; + if(!uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyThermostat/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes); + } + + if(!uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyThermostat/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes); + } + + // Init the attributes for that cluster + uic_mqtt_dotdot_unify_thermostat_attributes_init(); + + uic_mqtt_dotdot_by_group_unify_thermostat_init(); + + return SL_STATUS_OK; +} + sl_status_t uic_mqtt_dotdot_init() { @@ -94952,6 +95286,10 @@ sl_status_t uic_mqtt_dotdot_init() { status_flag = uic_mqtt_dotdot_descriptor_init(); } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_unify_thermostat_init(); + } + return status_flag; } @@ -95013,6 +95351,7 @@ void uic_mqtt_dotdot_publish_supported_commands( uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands(unid, endpoint_id); uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_commands(unid, 0); uic_mqtt_dotdot_descriptor_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_thermostat_publish_supported_commands(unid, endpoint_id); } void uic_mqtt_dotdot_publish_empty_supported_commands( @@ -95071,6 +95410,7 @@ void uic_mqtt_dotdot_publish_empty_supported_commands( uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands(unid, endpoint_id); uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_supported_commands(unid); uic_mqtt_dotdot_descriptor_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands(unid, endpoint_id); } // Publishing Cluster Revision for Basic Cluster @@ -108533,6 +108873,154 @@ void uic_mqtt_dotdot_descriptor_publish_empty_supported_commands( } } +// Publishing Cluster Revision for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback) { + uic_mqtt_dotdot_unify_thermostat_state_t unify_thermostat_new_state = {}; + uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_thermostat_new_state, + unify_thermostat_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { + uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_thermostat_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyThermostat/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/UnifyThermostat/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyThermostat/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + //////////////////////////////////////////////////////////////////////////////// // Generated Commands publications functions diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp index 156e7b356d..f030cf5892 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp @@ -367,6 +367,13 @@ sl_status_t uic_mqtt_dotdot_by_group_aox_position_estimation_init(); */ sl_status_t uic_mqtt_dotdot_by_group_descriptor_init(); +/** + * @brief Initialize UnifyThermostat dotdot bygroup command handlers + * + * @returns SL_STATUS_OK on success, error otherwise. + */ +sl_status_t uic_mqtt_dotdot_by_group_unify_thermostat_init(); + // clang-format on @@ -5052,6 +5059,27 @@ void uic_mqtt_dotdot_on_descriptor_WriteAttributes( const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callback pointers for by-unid + * /Commands/WriteAttributes messages + * + * @returns std::set of callbacks. + */ +std::set & get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UnifyThermostat/Commands/WriteAttributes + */ +// clang-format off +void uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length); + + // All bitmaps are defined as the cluster label for the bitmap plus the command/attribute name @@ -5891,6 +5919,42 @@ const std::vector, std::vector, std::vector>>> UnifyThermostatSupportedThermostatMode_bitmap_data { +{ {"Off", "bool", "0x1", "0"}, { +} }, +{ {"Heat", "bool", "0x2", "1"}, { +} }, +{ {"Cool", "bool", "0x4", "2"}, { +} }, +{ {"Auto", "bool", "0x8", "3"}, { +} }, +{ {"Auxiliary", "bool", "0x10", "4"}, { +} }, +{ {"Resume", "bool", "0x20", "5"}, { +} }, +{ {"Fan", "bool", "0x40", "6"}, { +} }, +{ {"Furnace", "bool", "0x80", "7"}, { +} }, +{ {"Dry", "bool", "0x100", "8"}, { +} }, +{ {"Moist", "bool", "0x200", "9"}, { +} }, +{ {"AutoChangeover", "bool", "0x400", "10"}, { +} }, +{ {"EnergyHeat", "bool", "0x800", "11"}, { +} }, +{ {"EnergyCool", "bool", "0x1000", "12"}, { +} }, +{ {"Away", "bool", "0x2000", "13"}, { +} }, +{ {"FullPower", "bool", "0x4000", "14"}, { +} }, +{ {"ManufacturerSpecific", "bool", "0x8000", "15"}, { +} } +}; +const dotdot_bitmap UnifyThermostatSupportedThermostatMode("UnifyThermostatSupportedThermostatMode", "Unknown UnifyThermostatSupportedThermostatMode", UnifyThermostatSupportedThermostatMode_bitmap_data); + const std::vector, std::vector>>> WindowCoveringConfigOrStatus_bitmap_data { { {"Operational", "bool", "0x1", "0"}, { } }, diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp index 43090fc989..40bf0316be 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp @@ -63117,3 +63117,208 @@ void uic_mqtt_dotdot_descriptor_attribute_device_type_list_callback_set(const ui // End of supported cluster. +/////////////////////////////////////////////////////////////////////////////// +// Callback pointers for UnifyThermostat +/////////////////////////////////////////////////////////////////////////////// +static uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_t uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback = nullptr; +static uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_t uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback = nullptr; + +/////////////////////////////////////////////////////////////////////////////// +// Attribute update handlers for UnifyThermostat +/////////////////////////////////////////////////////////////////////////////// +static void uic_mqtt_dotdot_on_unify_thermostat_thermostat_mode_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint8_t thermostat_mode = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UnifyThermostat::ThermostatMode: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + uint32_t tmp = get_enum_decimal_value("value", json_payload); + if (tmp == numeric_limits::max()) { + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + tmp = unify_thermostat_thermostat_mode_get_enum_value_number(json_payload.at("value").get()); + #elif defined(THERMOSTAT_MODE_ENUM_NAME_AVAILABLE) + tmp = thermostat_mode_get_enum_value_number(json_payload.at("value").get()); + #endif + } + thermostat_mode = static_cast(tmp); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + thermostat_mode + ); + +} +static void uic_mqtt_dotdot_on_unify_thermostat_supported_thermostat_mode_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint16_t supported_thermostat_mode = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UnifyThermostat::SupportedThermostatMode: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + supported_thermostat_mode = uic_dotdot_mqtt::get_bitmap_decimal_value("value", json_payload, UnifyThermostatSupportedThermostatMode); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + supported_thermostat_mode + ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Attribute init functions for UnifyThermostat +/////////////////////////////////////////////////////////////////////////////// +sl_status_t uic_mqtt_dotdot_unify_thermostat_attributes_init() +{ + std::string base_topic = "ucl/by-unid/+/+/"; + + std::string subscription_topic; + if(uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback) { + subscription_topic = base_topic + "UnifyThermostat/Attributes/ThermostatMode/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_thermostat_thermostat_mode_attribute_update); + } + if(uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback) { + subscription_topic = base_topic + "UnifyThermostat/Attributes/SupportedThermostatMode/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_unify_thermostat_supported_thermostat_mode_attribute_update); + } + + return SL_STATUS_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Callback setters and getters for UnifyThermostat +/////////////////////////////////////////////////////////////////////////////// +void uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_set(const uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback_t callback) +{ + uic_mqtt_dotdot_unify_thermostat_attribute_thermostat_mode_callback = callback; +} +void uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_set(const uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback_t callback) +{ + uic_mqtt_dotdot_unify_thermostat_attribute_supported_thermostat_mode_callback = callback; +} + +// End of supported cluster. + diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp index 0ee153812b..ce89c021f4 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp @@ -14799,3 +14799,34 @@ void uic_mqtt_dotdot_parse_descriptor_write_attributes( } + +/** + * @brief JSON parser for ::WriteAttributes command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( + nlohmann::json &jsn, + uic_mqtt_dotdot_unify_thermostat_state_t &new_state, + uic_mqtt_dotdot_unify_thermostat_updated_state_t &new_updated_state +) { + + + if (jsn.find("ThermostatMode") != jsn.end()) { + + uint32_t tmp = get_enum_decimal_value("ThermostatMode", jsn); + if (tmp == std::numeric_limits::max()) { + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + tmp = unify_thermostat_thermostat_mode_get_enum_value_number(jsn.at("ThermostatMode").get()); + #elif defined(THERMOSTAT_MODE_ENUM_NAME_AVAILABLE) + tmp = thermostat_mode_get_enum_value_number(jsn.at("ThermostatMode").get()); + #endif + } + new_state.thermostat_mode = tmp; + + new_updated_state.thermostat_mode = true; + } + + +} + diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp index 21f137181d..94e4e8594f 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp @@ -6071,6 +6071,18 @@ void uic_mqtt_dotdot_parse_descriptor_write_attributes( ); +/** + * @brief JSON parser for UnifyThermostat WriteAttributes command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( + nlohmann::json &jsn, + uic_mqtt_dotdot_unify_thermostat_state_t &new_state, + uic_mqtt_dotdot_unify_thermostat_updated_state_t &new_updated_state +); + + #endif //DOTDOT_MQTT_COMMAND_HELPERS_HPP /** @} end dotdot_mqtt_command_helpers */ diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp index a09f1a69cf..b8c197f9ed 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp @@ -11396,3 +11396,57 @@ void uic_mqtt_dotdot_descriptor_publish_generated_write_attributes_command( false); } + + +/** + * @brief Publishes an incoming/generated WriteAttributes command for + * the UnifyThermostat cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UnifyThermostat/GeneratedCommands/WriteAttributes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * @param attribute_values Values to assign to the attributes + * @param attribute_list List of attributes that are written + */ +void uic_mqtt_dotdot_unify_thermostat_publish_generated_write_attributes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_unify_thermostat_state_t attribute_values, + uic_mqtt_dotdot_unify_thermostat_updated_state_t attribute_list +){ + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UnifyThermostat/GeneratedCommands/WriteAttributes"; + + nlohmann::json json_object = nlohmann::json::object(); + + + if (attribute_list.thermostat_mode == true) { + + // This is a single value + + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + json_object["ThermostatMode"] = unify_thermostat_thermostat_mode_get_enum_value_name((uint32_t)attribute_values.thermostat_mode); + #else + json_object["ThermostatMode"] = static_cast(attribute_values.thermostat_mode); + #endif + + + } + + + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + std::string payload = json_object.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp index 5d85d166d8..b0168f71a4 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp @@ -366,6 +366,9 @@ static uic_mqtt_dotdot_by_group_aox_position_estimation_write_attributes_callbac static uic_mqtt_dotdot_by_group_descriptor_write_attributes_callback_t uic_mqtt_dotdot_by_group_descriptor_write_attributes_callback = nullptr; +static uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_t uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback = nullptr; + + // Callbacks setters @@ -1876,6 +1879,15 @@ void uic_mqtt_dotdot_by_group_descriptor_write_attributes_callback_set( +// Callbacks setters +void uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_set( + const uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback = callback; +} + + + // Callback function for incoming publications on ucl/by-group/+/Basic/Commands/ResetToFactoryDefaults static void uic_mqtt_dotdot_on_by_group_basic_reset_to_factory_defaults( @@ -23492,6 +23504,91 @@ sl_status_t uic_mqtt_dotdot_by_group_descriptor_init() + +static void uic_mqtt_dotdot_on_by_group_unify_thermostat_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback().empty())) { + try { + group_dispatch_callback(group_id, + "UnifyThermostat", + "WriteAttributes", + message, + message_length, + uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes); + + } catch (...) { + sl_log_debug(LOG_TAG, "UnifyThermostat: Unable to parse JSON payload.\n"); + return; + } + } else if (uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback != nullptr) { + + uic_mqtt_dotdot_unify_thermostat_state_t new_state = {}; + uic_mqtt_dotdot_unify_thermostat_updated_state_t new_updated_state = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyThermostat", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", ""); + return; + } + + uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback( + group_id, + new_state, + new_updated_state + ); + } +} + +sl_status_t uic_mqtt_dotdot_by_group_unify_thermostat_init() +{ + std::string subscription_topic; + const std::string topic_bygroup = TOPIC_BY_GROUP_PREFIX; + if(uic_mqtt_dotdot_by_group_unify_thermostat_write_attributes_callback) { + subscription_topic = topic_bygroup + "UnifyThermostat/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_unify_thermostat_WriteAttributes); + } + + return SL_STATUS_OK; +} + + + void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback) { // Check for uninitialized value in order to subscribe with on_group handlers @@ -23773,6 +23870,8 @@ void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback) uic_mqtt_subscribe("ucl/by-group/+/Descriptor/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_descriptor_WriteAttributes); + uic_mqtt_subscribe("ucl/by-group/+/UnifyThermostat/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_unify_thermostat_WriteAttributes); + } group_dispatch_callback = callback; diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp index e777d585ab..5cdf48696f 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp @@ -5064,6 +5064,71 @@ uint32_t tx_report_transmission_speed_get_enum_value_number(const std::string &s return std::numeric_limits::max(); } +// Enum to string map for UnifyThermostatThermostatMode +const std::map unify_thermostat_thermostat_mode_enum_id_to_string_map { + { 0, "Off" }, + { 1, "Heat" }, + { 2, "Cool" }, + { 3, "Auto" }, + { 4, "Auxiliary" }, + { 5, "Resume" }, + { 6, "Fan" }, + { 7, "Furnace" }, + { 8, "Dry" }, + { 9, "Moist" }, + { 10, "AutoChangeover" }, + { 11, "EnergyHeat" }, + { 12, "EnergyCool" }, + { 13, "Away" }, + { 15, "FullPower" }, + { 31, "ManufacturerSpecific" }, +}; + +// String to enum map for UnifyThermostatThermostatMode +const std::map unify_thermostat_thermostat_mode_enum_string_to_id_map { + { "Off", 0 }, + { "Heat", 1 }, + { "Cool", 2 }, + { "Auto", 3 }, + { "Auxiliary", 4 }, + { "Resume", 5 }, + { "Fan", 6 }, + { "Furnace", 7 }, + { "Dry", 8 }, + { "Moist", 9 }, + { "AutoChangeover", 10 }, + { "EnergyHeat", 11 }, + { "EnergyCool", 12 }, + { "Away", 13 }, + { "FullPower", 15 }, + { "ManufacturerSpecific", 31 }, +}; + +std::string unify_thermostat_thermostat_mode_get_enum_value_name( + uint32_t value) +{ + auto it = unify_thermostat_thermostat_mode_enum_id_to_string_map.find(value); + if (it != unify_thermostat_thermostat_mode_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t unify_thermostat_thermostat_mode_get_enum_value_number(const std::string &str) +{ + auto it = unify_thermostat_thermostat_mode_enum_string_to_id_map.find(str); + if (it != unify_thermostat_thermostat_mode_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + // Enum to string map for WindowCoveringWindowCoveringType const std::map window_covering_window_covering_type_enum_id_to_string_map { { 0, "Rollershade" }, @@ -9908,6 +9973,21 @@ std::string get_enum_value_name( #endif } + if (64789 == cluster_id) { + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + if (1 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_thermostatthermostat_mode instead of this: unify_thermostat_thermostat_mode + return unify_thermostat_thermostat_mode_get_enum_value_name(value); + } + #endif + #ifdef UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + if (2 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_thermostatsupported_thermostat_mode instead of this: unify_thermostat_supported_thermostat_mode + return unify_thermostat_supported_thermostat_mode_get_enum_value_name(value); + } + #endif + } + std::string value_name; return value_name; @@ -14376,6 +14456,21 @@ uint32_t get_enum_name_value( #endif } + if (64789 == cluster_id) { + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + if (1 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_thermostatthermostat_mode instead of this: unify_thermostat_thermostat_mode + return unify_thermostat_thermostat_mode_get_enum_value_number(name); + } + #endif + #ifdef UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + if (2 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: unify_thermostatsupported_thermostat_mode instead of this: unify_thermostat_supported_thermostat_mode + return unify_thermostat_supported_thermostat_mode_get_enum_value_number(name); + } + #endif + } + // No known numeric value is set for this string. // Return UINT32_MAX to indicate an error. @@ -15616,6 +15711,17 @@ uint32_t tx_report_transmission_speed_get_enum_value_number_c(const char *str) { return tx_report_transmission_speed_get_enum_value_number(std::string(str)); } +char *unify_thermostat_thermostat_mode_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", unify_thermostat_thermostat_mode_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t unify_thermostat_thermostat_mode_get_enum_value_number_c(const char *str) +{ + return unify_thermostat_thermostat_mode_get_enum_value_number(std::string(str)); +} char *window_covering_window_covering_type_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size) { diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp index a2d5d754d8..c5aa5ff47d 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp @@ -2812,3 +2812,46 @@ void uic_mqtt_dotdot_descriptor_publish_supported_generated_commands( } + +/** + * @brief Sends/Publishes a the SupportedGenerated commands for + * the UnifyThermostat cluster for a UNID/Endpoint + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UnifyThermostat/SupportedGeneratedCommands + * + * @param unid The UNID of the node on behalf of which the advertisment is made + * + * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made + * + * @param command_list Struct pointer with the fields value indicating if + * individual commands can be generated. + */ +void uic_mqtt_dotdot_unify_thermostat_publish_supported_generated_commands( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_unify_thermostat_supported_commands_t *command_list) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint); + topic += "/UnifyThermostat/SupportedGeneratedCommands"; + + // Assemble of vector of strings for the Supported Commands: + std::vector command_vector; + if (command_list->write_attributes == true) { + command_vector.emplace_back("WriteAttributes"); + } + + // JSONify, then Stringify + nlohmann::json json_payload; + json_payload["value"] = command_vector; + std::string string_payload = json_payload.dump(); + + // Publish to MQTT + uic_mqtt_publish(topic.c_str(), + string_payload.c_str(), + string_payload.length(), + true); + +} + diff --git a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include index 4884cdd28a..824a87d6a2 100644 --- a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include +++ b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include @@ -3649,6 +3649,7 @@ static void unset_all_callbacks() uic_mqtt_dotdot_protocol_controller_network_management_write_callback_clear(); uic_mqtt_dotdot_clear_protocol_controller_network_management_write_attributes_callbacks(); uic_mqtt_dotdot_clear_descriptor_write_attributes_callbacks(); + uic_mqtt_dotdot_clear_unify_thermostat_write_attributes_callbacks(); } static void reset_callback_counters() diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam index 88967fac0a..3dcd4e6cee 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam +++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam @@ -863,3 +863,7 @@ def DOTDOT_ATTRIBUTE_ID_PROTOCOL_CONTROLLER_NETWORK_MANAGEMENT_NETWORK_MANAGEMEN // This represents the attributes in the DotDot Descriptor cluster def DOTDOT_ATTRIBUTE_ID_DESCRIPTOR_DEVICE_TYPE_LIST 0xfd130000 +// This represents the attributes in the DotDot UnifyThermostat cluster +def DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE 0xfd150001 +def DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE 0xfd150002 + diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam index c4ef2c208c..830681a9e4 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam +++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam @@ -863,3 +863,7 @@ def zb_NetworkManagementState 0xfd120001 // This represents short CamelCase labels the attributes in the DotDot Descriptor cluster def zb_DeviceTypeList 0xfd130000 +// This represents short CamelCase labels the attributes in the DotDot UnifyThermostat cluster +def zb_ThermostatMode 0xfd150001 +def zb_SupportedThermostatMode 0xfd150002 + diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h index 16d75f051f..d4da0f50fc 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h +++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h @@ -77649,6 +77649,246 @@ bool dotdot_is_any_descriptor_writable_attribute_supported( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UnifyThermostat +//////////////////////////////////////////////////////////////////////////////// +// UnifyThermostat ThermostatMode +/** + * @brief Verifies if the DotDot UnifyThermostat - ThermostatMode is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if ThermostatMode is supported + * @returns false if ThermostatMode is not supported + */ +bool dotdot_is_supported_unify_thermostat_thermostat_mode ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UnifyThermostat - ThermostatMode attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns ThermostatMode attribute + */ +uint8_t dotdot_get_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UnifyThermostat - ThermostatMode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_thermostat_mode new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint8_t new_thermostat_mode + ); + +/** + * @brief Undefines the Reported value of the the DotDot UnifyThermostat - ThermostatMode + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_unify_thermostat_thermostat_mode_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UnifyThermostat - ThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_unify_thermostat_thermostat_mode_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UnifyThermostat - ThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_unify_thermostat_thermostat_mode_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UnifyThermostat - ThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_unify_thermostat_thermostat_mode_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UnifyThermostat - ThermostatMode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UnifyThermostat SupportedThermostatMode +/** + * @brief Verifies if the DotDot UnifyThermostat - SupportedThermostatMode is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportedThermostatMode is supported + * @returns false if SupportedThermostatMode is not supported + */ +bool dotdot_is_supported_unify_thermostat_supported_thermostat_mode ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UnifyThermostat - SupportedThermostatMode attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportedThermostatMode attribute + */ +uint16_t dotdot_get_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UnifyThermostat - SupportedThermostatMode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_supported_thermostat_mode new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_thermostat_mode + ); + +/** + * @brief Undefines the Reported value of the the DotDot UnifyThermostat - SupportedThermostatMode + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_unify_thermostat_supported_thermostat_mode_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UnifyThermostat - SupportedThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_unify_thermostat_supported_thermostat_mode_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UnifyThermostat - SupportedThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_unify_thermostat_supported_thermostat_mode_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UnifyThermostat - SupportedThermostatMode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_unify_thermostat_supported_thermostat_mode_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UnifyThermostat - SupportedThermostatMode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if a UNID/Endpoint supports any attribute for the UnifyThermostat + * Cluster + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if at least 1 attribute in the Attribute Store, false otherwise + */ +bool dotdot_is_any_unify_thermostat_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if a UNID/Endpoint supports any writable attribute for the + * UnifyThermostat Cluster + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if at least 1 writable attribute in the Attribute Store, false otherwise + */ +bool dotdot_is_any_unify_thermostat_writable_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h index 0118d5ba2d..2f5ddc1625 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h +++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h @@ -794,6 +794,9 @@ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_AOX_POSITION_ESTIMATION_POSITION , 0xfd1100 DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_PROTOCOL_CONTROLLER_NETWORK_MANAGEMENT_NETWORK_MANAGEMENT_STATE , 0xfd120001) // Attribute Defines for Descriptor DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_DESCRIPTOR_DEVICE_TYPE_LIST , 0xfd130000) +// Attribute Defines for UnifyThermostat +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE , 0xfd150001) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE , 0xfd150002) // Additional manually defined types: diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp index 2aba63453d..6b565306a7 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp @@ -25633,6 +25633,243 @@ static void descriptor_cluster_cluster_revision_callback( } +/** + * @brief Publishes the desired value of an updated attribute store node for + * the UnifyThermostat cluster. + * @param updated_node Updated attribute store node + * @param change Type of change applied + */ +static void unify_thermostat_cluster_publish_desired_value_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_desired_attribute_values_to_mqtt_enabled()) { + return; + } + if (change == ATTRIBUTE_DELETED || change == ATTRIBUTE_CREATED) { + return; + } + // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state. + if (ATTRIBUTE_STORE_INVALID_NODE + != attribute_store_get_first_parent_with_type( + updated_node, + DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + // clang-format off + // clang-format on + dotdot_endpoint_id_t endpoint_id = 0; + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + // clang-format on + + attribute_store_type_t type = attribute_store_get_node_type(updated_node); + if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) { + sl_log_debug(LOG_TAG, + "Warning: Invalid type for Attribute ID %d, " + "this should not happen.", + updated_node); + return; + } + + // If the value got updated but both Reported and Desired undefined, we skip publication + if (false == attribute_store_is_reported_defined(updated_node) + && false == attribute_store_is_desired_defined(updated_node)) { + sl_log_debug(LOG_TAG, + "Reported/Desired values are undefined. " + "Skipping publication"); + return; + } + + // clang-format off + try { + attribute_store::attribute attr(updated_node); + if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE) { + uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE) { + uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + } catch (std::exception &ex) { + sl_log_warning(LOG_TAG, "Failed to publish the Desired attribute value: %s", ex.what()); + } +} + +/** + * @brief Publishes the reported value of an updated attribute store node for + * the UnifyThermostat cluster. + * @param updated_node Updated attribute store node + * @param change Type of change applied + */ +static void unify_thermostat_cluster_publish_reported_value_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) { + return; + } + if (change == ATTRIBUTE_CREATED) { + return; + } + // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state. + if (ATTRIBUTE_STORE_INVALID_NODE + != attribute_store_get_first_parent_with_type( + updated_node, + DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + // clang-format off + // clang-format on + dotdot_endpoint_id_t endpoint_id = 0; + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + // clang-format on + + attribute_store_type_t type = attribute_store_get_node_type(updated_node); + if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) { + sl_log_debug(LOG_TAG, + "Warning: Invalid type for Attribute ID %d, " + "this should not happen.", + updated_node); + return; + } + + // Deletion case: + if (change == ATTRIBUTE_DELETED) { + // clang-format off + switch(type) { + case DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UnifyThermostat::ThermostatMode under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UnifyThermostat::SupportedThermostatMode under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + default: + break; + } + // clang-format on + return; + } + + // If the value got updated but undefined, we skip publication + if (false == attribute_store_is_reported_defined(updated_node)) { + sl_log_debug(LOG_TAG, "Reported value is undefined. Skipping publication"); + return; + } + + // Else we assume update case: + // clang-format off + try { + attribute_store::attribute attr(updated_node); + if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE) { + uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE) { + uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + } catch (std::exception &ex) { + sl_log_warning(LOG_TAG, "Failed to publish the Reported attribute value: %s", ex.what()); + } +} + +static void unify_thermostat_cluster_cluster_revision_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + dotdot_endpoint_id_t endpoint_id = 0; + // clang-format off + // clang-format on + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + + if ((change == ATTRIBUTE_CREATED) || (change == ATTRIBUTE_UPDATED)) { + // On attribute creation, make sure to publish the attribute revision for the first time + std::string cluster_revision_topic = base_topic + "/UnifyThermostat/Attributes/ClusterRevision"; + if (uic_mqtt_count_topics(cluster_revision_topic.c_str()) == 0) { + uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(base_topic.c_str(), 1); + } + } + + if (change == ATTRIBUTE_DELETED) { + // Check if we just erased the last attribute under a cluster, if yes, unretain + // the Cluster revision too. + if (false == dotdot_is_any_unify_thermostat_attribute_supported(unid, endpoint_id)) { + base_topic += "/UnifyThermostat"; + sl_log_debug(LOG_TAG, "No more attributes supported for UnifyThermostat cluster for UNID %s Endpoint %d. Unretaining leftover topics at %s",unid, endpoint_id, base_topic.c_str()); + uic_mqtt_unretain(base_topic.c_str()); + } + } +} + + // Initialization of the component. sl_status_t unify_dotdot_attribute_store_attribute_publisher_init() @@ -35675,6 +35912,34 @@ sl_status_t unify_dotdot_attribute_store_attribute_publisher_init() attribute_store_register_callback_by_type( descriptor_cluster_cluster_revision_callback, DOTDOT_ATTRIBUTE_ID_DESCRIPTOR_DEVICE_TYPE_LIST); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + unify_thermostat_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + unify_thermostat_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + unify_thermostat_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + unify_thermostat_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + unify_thermostat_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + unify_thermostat_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); return SL_STATUS_OK; } diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c index 5d488fb5a1..429f2b2e7b 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c @@ -4499,6 +4499,41 @@ static sl_status_t uic_mqtt_dotdot_descriptor_force_read_attributes_callback ( } return SL_STATUS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UnifyThermostat +//////////////////////////////////////////////////////////////////////////////// +static sl_status_t uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback ( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_unify_thermostat_updated_state_t attribute_list) { + + if (false == is_force_read_attributes_enabled()){ + return SL_STATUS_FAIL; + } + + if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + if (is_automatic_deduction_of_supported_commands_enabled()) { + return dotdot_is_any_unify_thermostat_attribute_supported(unid, endpoint_id) ? + SL_STATUS_OK : SL_STATUS_FAIL; + } else { + return SL_STATUS_FAIL; + } + } + + // Go and undefine everything that needs to be read again: + if (true == attribute_list.thermostat_mode) { + if (SL_STATUS_OK == dotdot_unify_thermostat_thermostat_mode_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UnifyThermostat::ThermostatMode under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.supported_thermostat_mode) { + if (SL_STATUS_OK == dotdot_unify_thermostat_supported_thermostat_mode_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UnifyThermostat::SupportedThermostatMode under %s - Endpoint %d", unid, endpoint_id); + } + } + return SL_STATUS_OK; +} // clang-format on //////////////////////////////////////////////////////////////////////////////// @@ -4609,6 +4644,8 @@ sl_status_t uic_mqtt_dotdot_set_descriptor_force_read_attributes_callback(&uic_mqtt_dotdot_descriptor_force_read_attributes_callback); + uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback(&uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback); + // clang-format on return SL_STATUS_OK; diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp index e170bb45b1..8edd663c27 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp @@ -83593,5 +83593,255 @@ bool dotdot_is_any_descriptor_writable_attribute_supported( const dotdot_endpoint_id_t endpoint_id) { + return false; +} +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UnifyThermostat +//////////////////////////////////////////////////////////////////////////////// +bool dotdot_is_supported_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + return attribute_store_node_exists(node); +} + +uint8_t dotdot_get_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + + uint8_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint8_t new_thermostat_mode + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_thermostat_mode, + sizeof(uint8_t)); + } + +sl_status_t dotdot_unify_thermostat_thermostat_mode_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_unify_thermostat_thermostat_mode_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_unify_thermostat_thermostat_mode_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_unify_thermostat_thermostat_mode_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_unify_thermostat_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + return attribute_store_node_exists(node); +} + +uint16_t dotdot_get_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + + uint16_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_thermostat_mode + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_supported_thermostat_mode, + sizeof(uint16_t)); + } + +sl_status_t dotdot_unify_thermostat_supported_thermostat_mode_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_unify_thermostat_supported_thermostat_mode_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_unify_thermostat_supported_thermostat_mode_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_unify_thermostat_supported_thermostat_mode_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_unify_thermostat_supported_thermostat_mode( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +bool dotdot_is_any_unify_thermostat_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + if (true == dotdot_is_supported_unify_thermostat_thermostat_mode(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_unify_thermostat_supported_thermostat_mode(unid, endpoint_id)) { + return true; + } + + return false; +} + +bool dotdot_is_any_unify_thermostat_writable_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + if (true == dotdot_is_supported_unify_thermostat_thermostat_mode(unid, endpoint_id)) { + return true; + } + return false; } diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp index 0423e9305d..bcfbe3de55 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp @@ -17311,6 +17311,54 @@ sl_status_t unify_dotdot_attribute_store_registration_init() // clang-format off // clang-format on + { + // enum8 // enum8 // uint8_t + std::string attribute_type_string = "uint8_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UnifyThermostat ThermostatMode, " + "type: enum8 // uint8_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_THERMOSTAT_MODE, + "ZCL UnifyThermostat ThermostatMode", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // map16 // map16 // uint16_t + std::string attribute_type_string = "uint16_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UnifyThermostat SupportedThermostatMode, " + "type: map16 // uint16_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE, + "ZCL UnifyThermostat SupportedThermostatMode", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + // Additional attributes: for (auto const &a: zcl_additional_attribute_schema) { status |= attribute_store_register_type(a.type, diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c index f45d19784b..d40eedb94e 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c @@ -2585,6 +2585,40 @@ static sl_status_t descriptor_cluster_write_attributes_callback( endpoint_id); return SL_STATUS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UnifyThermostat +//////////////////////////////////////////////////////////////////////////////// +// WriteAttribute Callbacks unify_thermostat +static sl_status_t unify_thermostat_cluster_write_attributes_callback( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_unify_thermostat_state_t attributes, + uic_mqtt_dotdot_unify_thermostat_updated_state_t updated_attributes) +{ + if (false == is_write_attributes_enabled()) { + return SL_STATUS_FAIL; + } + + if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + if (is_automatic_deduction_of_supported_commands_enabled()) { + return dotdot_is_any_unify_thermostat_writable_attribute_supported(unid, endpoint_id) ? + SL_STATUS_OK : SL_STATUS_FAIL; + } else { + return SL_STATUS_FAIL; + } + } + + sl_log_debug(LOG_TAG, + "unify_thermostat: Incoming WriteAttributes command for %s, endpoint %d.\n", + unid, + endpoint_id); + if (true == updated_attributes.thermostat_mode) { + sl_log_debug(LOG_TAG, "Updating desired value for ThermostatMode attribute"); + dotdot_set_unify_thermostat_thermostat_mode(unid, endpoint_id, DESIRED_ATTRIBUTE, attributes.thermostat_mode); + } + return SL_STATUS_OK; +} // clang-format on //////////////////////////////////////////////////////////////////////////////// @@ -2752,6 +2786,9 @@ sl_status_t uic_mqtt_dotdot_set_descriptor_write_attributes_callback( &descriptor_cluster_write_attributes_callback); + uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback( + &unify_thermostat_cluster_write_attributes_callback); + // clang-format on return SL_STATUS_OK; diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c index fda0a48f1a..3470aa3ede 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c @@ -1312,6 +1312,16 @@ uic_mqtt_dotdot_descriptor_write_attributes_callback_t get_uic_mqtt_dotdot_descr return test_uic_mqtt_dotdot_descriptor_write_attributes_callback; } +static uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t test_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback = NULL; +static uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t test_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback = NULL; + +uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t get_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback(){ + return test_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback; +} +uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback(){ + return test_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; +} + // clang-format on #define TEST_UNID "test-unid-123" @@ -2878,6 +2888,16 @@ void set_uic_mqtt_dotdot_descriptor_write_attributes_callback_stub( { test_uic_mqtt_dotdot_descriptor_write_attributes_callback = callback; } +void set_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_stub( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback = callback; +} +void set_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_stub( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback = callback; +} // clang-format on // Test functions @@ -3798,6 +3818,12 @@ void setUp() test_uic_mqtt_dotdot_descriptor_write_attributes_callback = NULL; uic_mqtt_dotdot_set_descriptor_write_attributes_callback_Stub( &set_uic_mqtt_dotdot_descriptor_write_attributes_callback_stub); + test_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback = NULL; + uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback_Stub( + &set_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_stub); + test_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback = NULL; + uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback_Stub( + &set_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_stub); // clang-format on group_command_dispatch = NULL; @@ -4560,6 +4586,8 @@ void test_automatic_deduction_of_supported_commands() TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_aox_position_estimation_position(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_protocol_controller_network_management_network_management_state(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_descriptor_device_type_list(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_thermostat_thermostat_mode(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_unify_thermostat_supported_thermostat_mode(expected_unid,expected_endpoint_id) ); // clang-format on // ColorControl checks the value in the bitmask: diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h index 5d7b13dc5e..ec8e607e04 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h @@ -793,4 +793,8 @@ uic_mqtt_dotdot_descriptor_force_read_attributes_callback_t get_uic_mqtt_dotdot_descriptor_force_read_attributes_callback(); uic_mqtt_dotdot_descriptor_write_attributes_callback_t get_uic_mqtt_dotdot_descriptor_write_attributes_callback(); + + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t get_uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback(); + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback(); + #endif // UNIFY_DOTDOT_ATTRIBUTE_STORE_TEST_H \ No newline at end of file