//----------------------------------------------------------------------------- // // ValueSchedule.cpp // // A one day schedule for the Climate Control Schedule command class // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OpenZWave. // // OpenZWave is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation, either version 3 of the License, // or (at your option) any later version. // // OpenZWave is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with OpenZWave. If not, see . // //----------------------------------------------------------------------------- #include #include #include "../tinyxml.h" #include "ValueSchedule.h" #include "../Msg.h" #include "../platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueSchedule::ValueSchedule ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity ): Value( _homeId, _nodeId, _genre, _commandClassId, _instance, _index, ValueID::ValueType_Byte, _label, _units, _readOnly, _writeOnly, false, _pollIntensity ), m_numSwitchPoints( 0 ) { } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueSchedule::ValueSchedule ( ): Value(), m_numSwitchPoints( 0 ) { } //----------------------------------------------------------------------------- // // Apply settings from XML //----------------------------------------------------------------------------- void ValueSchedule::ReadXML ( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ) { Value::ReadXML( _homeId, _nodeId, _commandClassId, _valueElement ); // Read in the switch points TiXmlElement const* child = _valueElement->FirstChildElement(); while( child ) { char const* str = child->Value(); if( str ) { if( !strcmp( str, "SwitchPoint" ) ) { int intVal; uint8 hours = 0; if( TIXML_SUCCESS == child->QueryIntAttribute( "hours", &intVal ) ) { hours = (uint8)intVal; } uint8 minutes = 0; if( TIXML_SUCCESS == child->QueryIntAttribute( "minutes", &intVal ) ) { minutes = (uint8)intVal; } int8 setback = 0; if( TIXML_SUCCESS == child->QueryIntAttribute( "setback", &intVal ) ) { setback = (int8)intVal; } SetSwitchPoint( hours, minutes, setback ); } } child = child->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void ValueSchedule::WriteXML ( TiXmlElement* _valueElement ) { Value::WriteXML( _valueElement ); for( uint8 i=0; iLinkEndChild( switchPointElement ); snprintf( str, sizeof(str), "%d", hours ); switchPointElement->SetAttribute( "hours", str ); snprintf( str, sizeof(str), "%d", minutes ); switchPointElement->SetAttribute( "minutes", str ); snprintf( str, sizeof(str), "%d", setback ); switchPointElement->SetAttribute( "setback", str ); } } } //----------------------------------------------------------------------------- // // Set a new value in the device //----------------------------------------------------------------------------- bool ValueSchedule::Set ( ) { // Set the value in the device. // TODO this needs to be checked to make sure it works as intended return Value::Set(); } //----------------------------------------------------------------------------- // // A value in a device has been refreshed //----------------------------------------------------------------------------- void ValueSchedule::OnValueRefreshed ( ) { // TODO: do schedules ever report spurious values and need rechecking like other value types? // See, for example, ValueShort::OnValueRefreshed Value::OnValueChanged(); } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- bool ValueSchedule::SetSwitchPoint ( uint8 const _hours, uint8 const _minutes, int8 const _setback ) { // Find where to insert this switch point. They must be sorted by ascending time value. uint8 i; uint8 insertAt = 0; for( i=0; i _minutes ) { break; } } else if( m_switchPoints[i].m_hours > _hours ) { break; } ++insertAt; } if( m_numSwitchPoints >= 9 ) { // The schedule is full return false; } // Shuffle any later switch points out of the way for( i=m_numSwitchPoints; i>insertAt; --i ) { m_switchPoints[i].m_hours = m_switchPoints[i-1].m_hours; m_switchPoints[i].m_minutes = m_switchPoints[i-1].m_minutes; m_switchPoints[i].m_setback = m_switchPoints[i-1].m_setback; } // Insert the new switch point m_switchPoints[insertAt].m_hours = _hours; m_switchPoints[insertAt].m_minutes = _minutes; m_switchPoints[insertAt].m_setback = _setback; ++m_numSwitchPoints; return true; } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- bool ValueSchedule::RemoveSwitchPoint ( uint8 const _idx ) { if( _idx >= m_numSwitchPoints ) { // _idx is out of range return false; } // Shuffle any later switch points down to fill the gap for( uint8 i=_idx; i<(m_numSwitchPoints-1); ++i ) { m_switchPoints[i].m_hours = m_switchPoints[i+1].m_hours; m_switchPoints[i].m_minutes = m_switchPoints[i+1].m_minutes; m_switchPoints[i].m_setback = m_switchPoints[i+1].m_setback; } --m_numSwitchPoints; return true; } //----------------------------------------------------------------------------- // // Get the values of a switch point //----------------------------------------------------------------------------- bool ValueSchedule::GetSwitchPoint ( uint8 const _idx, uint8* o_hours, uint8* o_minutes, int8* o_setback )const { if( _idx >= m_numSwitchPoints ) { // _idx is out of range return false; } if( o_hours ) { *o_hours = m_switchPoints[_idx].m_hours; } if( o_minutes ) { *o_minutes = m_switchPoints[_idx].m_minutes; } if( o_setback ) { *o_setback = m_switchPoints[_idx].m_setback; } return true; } //----------------------------------------------------------------------------- // // Get the index of the switch point at the specified time //----------------------------------------------------------------------------- bool ValueSchedule::FindSwitchPoint ( uint8 const _hours, uint8 const _minutes, uint8* o_idx )const { for( uint8 i=0; i _minutes ) { // Gone past any possible match return false; } } else if( m_switchPoints[i].m_hours > _hours ) { // Gone past any possible match return false; } } // No match found return false; }