3434#include " platform/Log.h"
3535
3636#include " value_classes/ValueDecimal.h"
37+ #include " value_classes/ValueByte.h"
3738
3839#include " tinyxml.h"
3940
@@ -45,7 +46,9 @@ enum ThermostatSetpointCmd
4546 ThermostatSetpointCmd_Get = 0x02 ,
4647 ThermostatSetpointCmd_Report = 0x03 ,
4748 ThermostatSetpointCmd_SupportedGet = 0x04 ,
48- ThermostatSetpointCmd_SupportedReport = 0x05
49+ ThermostatSetpointCmd_SupportedReport = 0x05 ,
50+ ThermostatSetpointCmd_CapabilitiesGet = 0x09 ,
51+ ThermostatSetpointCmd_CapabilitiesReport = 0x0A
4952};
5053
5154enum
@@ -257,6 +260,20 @@ bool ThermostatSetpoint::HandleMsg
257260 {
258261 if ( ( _data[i] & (1 <<bit) ) != 0 )
259262 {
263+ if (GetVersion () >= 3 )
264+ {
265+ Msg* msg = new Msg (" ThermostatSetpointCmd_CapabilitesGet" , GetNodeId (), REQUEST , FUNC_ID_ZW_SEND_DATA , true , true , FUNC_ID_APPLICATION_COMMAND_HANDLER , GetCommandClassId ());
266+ msg->SetInstance (this , _instance);
267+ msg->Append (GetNodeId ());
268+ msg->Append (3 );
269+ msg->Append (GetCommandClassId ());
270+ msg->Append (ThermostatSetpointCmd_CapabilitiesGet);
271+ uint8 type = ((i - 1 ) << 3 ) + bit;
272+ msg->Append (type);
273+ msg->Append (GetDriver ()->GetTransmitOptions ());
274+ GetDriver ()->SendMsg (msg, OpenZWave::Driver::MsgQueue_Query);
275+ Log::Write (LogLevel_Info, GetNodeId (), " Requested Thermostat Setpoint Capabilities" );
276+ }
260277 // Add supported setpoint
261278 int32 index = (int32)((i-1 )<<3 ) + bit + m_setPointBase;
262279 if ( index < ThermostatSetpoint_Count )
@@ -273,6 +290,46 @@ bool ThermostatSetpoint::HandleMsg
273290 return true ;
274291 }
275292
293+ if (ThermostatSetpointCmd_CapabilitiesReport == (ThermostatSetpointCmd) _data[0 ])
294+ {
295+ if (Node* node = GetNodeUnsafe ())
296+ {
297+ // We have received the capabilities for supported setpoint Type
298+ uint8 scale;
299+ uint8 min_precision = 0 ;
300+ uint8 max_precision = 0 ;
301+ uint8 size = _data[2 ] & 0x07 ;
302+ string minValue = ExtractValue (&_data[2 ], &scale, &min_precision);
303+ string maxValue = ExtractValue (&_data[2 + size + 1 ], &scale, &max_precision);
304+
305+ Log::Write (LogLevel_Info, GetNodeId (), " Received capabilities of thermostat setpoint type %d, min %s (field size: %i bytes, precision: %i decimals) max %s (precision: %i decimals)" , (int ) _data[1 ], minValue.c_str (), size, min_precision, maxValue.c_str (), max_precision);
306+
307+ uint8 index = _data[1 ];
308+
309+ // JFD: Porting the Z-TRM3 minsize fix: branch 1.6 has a different way of managing ValueIDs and
310+ // explicitely defines values for setpoint minsize and precision. The index part is 8 bits unsigned
311+ // for both branches. We use an arbitrary unused index value for storing the minsize and precision.
312+ // We don't store the minimum and maximum setpoint values as we have no use for them.
313+ #define ValueID_Index_ThermostatSetpoint_SetPointMinSize 250
314+ #define ValueID_Index_ThermostatSetpoint_SetPointPrecision 251
315+
316+ if (index < ThermostatSetpoint_Count)
317+ {
318+ string setpointName = c_setpointName[index];
319+
320+ if (m_enforceMinSizePrecision) {
321+ // Retain the size of the minimum temperature as the minimum field size for the temperature and the minimum precision as the base precision for future communication
322+ node->CreateValueByte (ValueID::ValueGenre_User, GetCommandClassId (), _instance, ValueID_Index_ThermostatSetpoint_SetPointMinSize, setpointName + " _setpointminsize" , " B" , false , false , size, 0 );
323+ node->CreateValueByte (ValueID::ValueGenre_User, GetCommandClassId (), _instance, ValueID_Index_ThermostatSetpoint_SetPointPrecision, setpointName + " _setpointprecision" , " D" , false , false , min_precision, 0 );
324+ Log::Write (LogLevel_Info, GetNodeId (), " EnforceMinSizePrecision enabled, retained min size and min precision from capability report for setpoint command" );
325+ }
326+ // node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatSetpoint::Unused_0_Minimum + index, setpointName + "_minimum", "C", false, false, minValue, 0);
327+ // node->CreateValueDecimal(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_ThermostatSetpoint::Unused_0_Maximum + index, setpointName + "_maximum", "C", false, false, maxValue, 0);
328+ Log::Write (LogLevel_Info, GetNodeId (), " Added setpoint: %s" , setpointName.c_str ());
329+ }
330+
331+ }
332+ }
276333 return false ;
277334}
278335
@@ -289,15 +346,26 @@ bool ThermostatSetpoint::SetValue
289346 {
290347 ValueDecimal const * value = static_cast <ValueDecimal const *>(&_value);
291348 uint8 scale = strcmp ( " C" , value->GetUnits ().c_str () ) ? 1 : 0 ;
349+ int8 setpointminsize = 0 ; // Minimum number of bytes to express the setpoint value, optionally cached from the capabilities report
350+ int8 setpointprecision = 0 ; // Minimum precision express the setpoint value, optionally cached from the capabilities report
351+
352+ if (auto const *minsizeValue = static_cast <ValueByte const *>(GetValue (_value.GetID ().GetInstance (), ValueID_Index_ThermostatSetpoint_SetPointMinSize)))
353+ {
354+ setpointminsize = minsizeValue->GetValue ();
355+ }
356+ if (auto const *precisionValue = static_cast <ValueByte const *>(GetValue (_value.GetID ().GetInstance (), ValueID_Index_ThermostatSetpoint_SetPointPrecision)))
357+ {
358+ setpointprecision = precisionValue->GetValue ();
359+ }
292360
293361 Msg* msg = new Msg ( " ThermostatSetpointCmd_Set" , GetNodeId (), REQUEST , FUNC_ID_ZW_SEND_DATA , true );
294362 msg->SetInstance ( this , _value.GetID ().GetInstance () );
295363 msg->Append ( GetNodeId () );
296- msg->Append ( 4 + GetAppendValueSize ( value->GetValue () ) );
364+ msg->Append ( 4 + GetAppendValueSize (value->GetValue (), setpointminsize, setpointprecision ) );
297365 msg->Append ( GetCommandClassId () );
298366 msg->Append ( ThermostatSetpointCmd_Set );
299367 msg->Append ( value->GetID ().GetIndex () );
300- AppendValue ( msg, value->GetValue (), scale );
368+ AppendValue ( msg, value->GetValue (), scale, setpointminsize, setpointprecision );
301369 msg->Append ( GetDriver ()->GetTransmitOptions () );
302370 GetDriver ()->SendMsg ( msg, Driver::MsgQueue_Send );
303371 return true ;
0 commit comments