diff --git a/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam b/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam
index 233aaeaea1..830d2d810d 100644
--- a/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam
+++ b/applications/zpc/components/dotdot_mapper/rules/Thermostat.uam
@@ -6,17 +6,6 @@ def zwSENSOR_MULTILEVEL_SCALE 0x3104
def zwSENSOR_MULTILEVEL_SENSOR_VALUE 0x3105
def zwMULTILEVEL_SUPPORTED_SENSOR_TYPES 0x3106
-//Thermostat setpoint CC
-def zwTHERMOSTAT_SETPOINT_VERSION 0x4301
-def zwTHERMOSTAT_SUPPORTED_SETPOINT_TYPES 0x4302
-def zwTHERMOSTAT_SETPOINT_TYPE 0x4303
-def zwTHERMOSTAT_SETPOINT_VALUE 0x4304
-def zwTHERMOSTAT_SETPOINT_VALUE_SCALE 0x4305
-def zwTHERMOSTAT_SETPOINT_MIN_VALUE 0x4306
-def zwTHERMOSTAT_SETPOINT_MIN_VALUE_SCALE 0x4307
-def zwTHERMOSTAT_SETPOINT_MAX_VALUE 0x4308
-def zwTHERMOSTAT_SETPOINT_MAX_VALUE_SCALE 0x4309
-
def zwTHERMOSTAT_MODE_VERSION 0x4001
def zwTHERMOSTAT_MODE 0x4002
def zwTHERMOSTAT_SUPPORTED_MODES 0x4003
@@ -54,75 +43,10 @@ def zb_ACLouverPosition 0x02010045
def zb_ACCoilTemperature 0x02010046
def zb_ACCapacityFormat 0x02010047
-def thermostat_setpoint_supported (e'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE | e'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE)
-
scope 0 {
- // We map Setpoint setpoint_type 0x01 (HEATING) and 0x02 (COOLING)
- // The Z-Wave units are converted into milli units, in ZigBee is should be
- // deci-celsius.
- // A value scale of 1 means fahrenheit
-
- // Heating
- r'zb_OccupiedHeatingSetpoint =
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 0 )
- (r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE / 10)
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 1 )
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE - 32000) * 5) / 90)
- undefined
-
- d'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE =
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 0 )
- (d'zb_OccupiedHeatingSetpoint*10)
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 1 )
- (((d'zb_OccupiedHeatingSetpoint)*90) / 5 + 32000)
- undefined
-
- r'zb_MinHeatSetpointLimit =
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MIN_VALUE_SCALE == 0)
- (r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MIN_VALUE / 10)
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MIN_VALUE_SCALE == 1)
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MIN_VALUE - 32000) * 5) / 90)
- undefined
-
- r'zb_MaxHeatSetpointLimit =
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MAX_VALUE_SCALE == 0)
- (r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MAX_VALUE / 10)
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MAX_VALUE_SCALE == 1)
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[1].zwTHERMOSTAT_SETPOINT_MAX_VALUE - 32000) * 5) / 90)
- undefined
-
- // Cooling
- r'zb_OccupiedCoolingSetpoint =
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 0)
- (r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE / 10 )
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 1)
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE - 32000) * 5) / 90)
- undefined
-
- r'zb_MinCoolSetpointLimit =
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MIN_VALUE_SCALE == 0)
- (r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MIN_VALUE / 10)
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MIN_VALUE_SCALE == 1)
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MIN_VALUE - 32000) * 5) / 90)
- undefined
-
- r'zb_MaxCoolSetpointLimit =
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MAX_VALUE_SCALE == 0)
- (r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MAX_VALUE / 10)
- if(r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MAX_VALUE_SCALE == 1)
- (((r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_MAX_VALUE - 32000) * 5) / 90)
- undefined
-
- d'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE =
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 0)
- (d'zb_OccupiedCoolingSetpoint*10)
- if( r'zwTHERMOSTAT_SETPOINT_TYPE[2].zwTHERMOSTAT_SETPOINT_VALUE_SCALE == 1 )
- (((d'zb_OccupiedCoolingSetpoint)*90) / 5 + 32000)
- undefined
-
// Local Temperature
r'zb_LocalTemperature =
- if(thermostat_setpoint_supported == 0) undefined
+ // if(thermostat_setpoint_supported == 0) undefined
if(r'zwSENSOR_MULTILEVEL_SENSOR_TYPE[1].zwSENSOR_MULTILEVEL_SCALE == 0)
(r'zwSENSOR_MULTILEVEL_SENSOR_TYPE[1].zwSENSOR_MULTILEVEL_SENSOR_VALUE / 10)
if(r'zwSENSOR_MULTILEVEL_SENSOR_TYPE[1].zwSENSOR_MULTILEVEL_SCALE == 1)
diff --git a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
index f9ed19a135..c300e32330 100644
--- a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
+++ b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h
@@ -673,26 +673,40 @@ DEFINE_ATTRIBUTE(
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE,
((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x03))
+// WARNING : applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.cpp
+// use the attributes ID to determine value scale and precision. (+1 for scale and +2 for precision)
+// Be careful if you change the ID
+#define SETPOINT_SCALE_ATTRIBUTE_ID_OFFSET 1
+#define SETPOINT_PRECISION_ATTRIBUTE_ID_OFFSET 2
+
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE,
((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x04))
+// 0x05
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE_SCALE,
- ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x05))
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x04 + SETPOINT_SCALE_ATTRIBUTE_ID_OFFSET)))
+// 0x06
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE_PRECISION,
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x04 + SETPOINT_PRECISION_ATTRIBUTE_ID_OFFSET)))
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE,
- ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x06))
-
-DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE_SCALE,
((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x07))
+// 0x08
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE_SCALE,
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x07 + SETPOINT_SCALE_ATTRIBUTE_ID_OFFSET)))
+// 0x09
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE_PRECISION,
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x07 + SETPOINT_PRECISION_ATTRIBUTE_ID_OFFSET)))
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE,
- ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x08))
-
-DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_SCALE,
- ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x09))
-
-DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE_PRECISION,
((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x0A))
+// 0x0B
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_SCALE,
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x0A + SETPOINT_SCALE_ATTRIBUTE_ID_OFFSET)))
+// 0x0C
+DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_PRECISION,
+ ((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | (0x0A + SETPOINT_PRECISION_ATTRIBUTE_ID_OFFSET)))
+
/////////////////////////////////////////////////
// Wakeup command class
diff --git a/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_thermostat_setpoint_types.h b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_thermostat_setpoint_types.h
new file mode 100644
index 0000000000..42f020510b
--- /dev/null
+++ b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_thermostat_setpoint_types.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * # License
+ * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+
+/**
+ * @defgroup zpc_attribute_store_command_classes_types Type definitions for attribute storage of Command Classes
+ * @ingroup zpc_attribute_store
+ * @brief Type definitions for Command Classes, used for @ref attribute_store storage.
+ *
+ */
+
+/**
+ * @defgroup zwave_command_class_thermostat_setpoint_types Type definitions for attribute storage of the Thermostat SetPoint Command Class
+ * @ingroup zpc_attribute_store_command_classes_types
+ * @brief Type definitions for the Thermostat SetPoint Command Class.
+ *
+ * @{
+ */
+
+#ifndef ZWAVE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPES_H
+#define ZWAVE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPES_H
+
+#define SETPOINT_TYPE_HEATING 1
+#define SETPOINT_TYPE_COOLING 2
+
+// Should be uint8_t, but kept int8_t for legacy reasons
+typedef int8_t thermostat_setpoint_type_t;
+typedef int32_t thermostat_setpoint_value_t;
+// Should be uint8_t, but kept uint32_t for legacy reasons
+typedef uint32_t thermostat_setpoint_scale_t;
+typedef uint8_t thermostat_setpoint_precision_t;
+
+
+#endif //ZWAVE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPES_H
+/** @} end zwave_command_class_thermostat_setpoint_types */
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 6f18154279..eabd22e3cd 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
@@ -302,8 +302,12 @@ static const std::vector attribute_schema = {
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE, "Min Value", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, I32_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE_SCALE, "Min Value Scale", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U32_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MIN_VALUE_PRECISION, "Min Value Precision", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U8_STORAGE_TYPE},
+
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE, "Max Value", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, I32_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_SCALE, "Max Value Scale", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U32_STORAGE_TYPE},
+ {ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_PRECISION, "Max Value Precision", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U8_STORAGE_TYPE},
+
/////////////////////////////////////////////////////////////////////
// Supervision Command Class attributes
/////////////////////////////////////////////////////////////////////
diff --git a/applications/zpc/components/zwave_command_classes/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/CMakeLists.txt
index 90bec52fee..654a24788e 100644
--- a/applications/zpc/components/zwave_command_classes/CMakeLists.txt
+++ b/applications/zpc/components/zwave_command_classes/CMakeLists.txt
@@ -45,7 +45,7 @@ add_library(
src/zwave_command_class_switch_color.c
src/zwave_command_class_switch_multilevel.c
src/zwave_command_class_thermostat_mode.c
- src/zwave_command_class_thermostat_setpoint.c
+ src/zwave_command_class_thermostat_setpoint.cpp
src/zwave_command_class_time.c
src/zwave_command_class_user_code.c
src/zwave_command_class_version.c
diff --git a/applications/zpc/components/zwave_command_classes/include/zwave_command_classes_utils.h b/applications/zpc/components/zwave_command_classes/include/zwave_command_classes_utils.h
index 7b8c18954e..3ccc5706ee 100644
--- a/applications/zpc/components/zwave_command_classes/include/zwave_command_classes_utils.h
+++ b/applications/zpc/components/zwave_command_classes/include/zwave_command_classes_utils.h
@@ -56,8 +56,8 @@ typedef struct zwave_minimum_frame {
} zwave_minimum_frame_t;
// Helper macros
-#define FAHRENHEIT_TO_DEGREES(value) ((value - 32.0F) * 5 / 9);
-#define DEGREES_TO_FAHRENHEIT(value) (value * 9 / 5.0F) + 32;
+#define FAHRENHEIT_TO_DEGREES(value) ((value - 32.0) * 5 / 9);
+#define DEGREES_TO_FAHRENHEIT(value) (value * 9 / 5.0) + 32;
// Constants
/// Additional delay in ms to wait before issuing a Get Command
@@ -214,7 +214,33 @@ int32_t get_signed_value_from_frame_and_size(const uint8_t *frame,
*/
uint32_t get_unsigned_value_from_frame_and_size(const uint8_t *frame,
uint8_t size);
+
/**
+ * @brief Convert a value from the Z-Wave world (precision = [0..7] and C° + F) into a UCL (Zigbee) world (precision = 2 and C°)
+ *
+ * @param zwave_value Current Z-Wave value
+ * @param zwave_precision Reported Z-Wave precision
+ * @param zwave_scale Reported Z-Wave scale (0 : C°, 1 : F)
+ *
+ * @return int16_t UCL temperature. Rounded down if Z-Wave precision is too high.
+ */
+int16_t zwave_temperature_to_ucl_temperature(int32_t zwave_value,
+ uint8_t zwave_precision,
+ uint8_t zwave_scale);
+
+/**
+ * @brief Convert a value from the UCL world (Zigbee) (precision = 2 and C°) to the ZWave world (precision = [0..7] and C° + F)
+ *
+ * @param ucl_value Current UCL value
+ * @param zwave_precision Expected Z-Wave precision
+ * @param zwave_scale Expected Z-Wave scale (0 : C°, 1 : F)
+ *
+ * @return int32_t Z-Wave temperature with given precision and scale.
+ */
+int32_t ucl_temperature_to_zwave_temperature(int16_t ucl_value,
+ uint8_t zwave_precision,
+ uint8_t zwave_scale);
+ /**
* @brief Converts a clock_time_t duration to a Z-Wave Command Class duration
* byte
*
@@ -224,7 +250,7 @@ uint32_t get_unsigned_value_from_frame_and_size(const uint8_t *frame,
* @param time The system time duration
* @returns uint8_t The corresponding Z-Wave duration encoding.
*/
-uint8_t time_to_zwave_duration(clock_time_t time);
+ uint8_t time_to_zwave_duration(clock_time_t time);
/**
* @brief Converts a duration byte encoded for a Z-Wave command class and returns
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.cpp
similarity index 53%
rename from applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.c
rename to applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.cpp
index 6c304586bd..fde4d1e9de 100644
--- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.c
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_thermostat_setpoint.cpp
@@ -13,6 +13,7 @@
// Includes from this component
#include "zwave_command_class_thermostat_setpoint.h"
+#include "zwave_command_class_thermostat_setpoint_types.h"
#include "zwave_command_classes_utils.h"
// Includes from other components
@@ -24,28 +25,72 @@
#include "zpc_attribute_store_network_helper.h"
#include "attribute_store_defined_attribute_types.h"
+#include "attribute_store_type_registration.h"
#include "attribute_store_helper.h"
#include "attribute_store.h"
#include "attribute_resolver.h"
// Generic includes
#include
+#include