Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-35: Control over Size & Precision in Thermostat Setpoint CC #36

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 1 addition & 77 deletions applications/zpc/components/dotdot_mapper/rules/Thermostat.uam
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Expand Up @@ -673,23 +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))

((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x0A))
// 0x0B
DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_MAX_VALUE_SCALE,
((COMMAND_CLASS_THERMOSTAT_SETPOINT << 8) | 0x09))
((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
Expand Down
@@ -0,0 +1,44 @@
/******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
******************************************************************************
* 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 */
Expand Up @@ -298,10 +298,16 @@ static const std::vector<attribute_schema_t> attribute_schema = {
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, "Thermostat Setpoint Type", ATTRIBUTE_ENDPOINT_ID, I8_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE, "Value", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, I32_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE_SCALE, "Value Scale", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U32_STORAGE_TYPE},
{ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_VALUE_PRECISION, "Value Precision", ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SETPOINT_TYPE, U8_STORAGE_TYPE},

{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
/////////////////////////////////////////////////////////////////////
Expand Down
Expand Up @@ -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
Expand Down
Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand All @@ -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
Expand Down