1 //----------------------------------------------------------------------------- 2 // 3 // Clock.cpp 4 // 5 // Implementation of the Z-Wave COMMAND_CLASS_CLOCK 6 // 7 // Copyright (c) 2010 Mal Lansell <openzwave@lansell.org> 8 // 9 // SOFTWARE NOTICE AND LICENSE 10 // 11 // This file is part of OpenZWave. 12 // 13 // OpenZWave is free software: you can redistribute it and/or modify 14 // it under the terms of the GNU Lesser General Public License as published 15 // by the Free Software Foundation, either version 3 of the License, 16 // or (at your option) any later version. 17 // 18 // OpenZWave is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU Lesser General Public License for more details. 22 // 23 // You should have received a copy of the GNU Lesser General Public License 24 // along with OpenZWave. If not, see <http://www.gnu.org/licenses/>. 25 // 26 //----------------------------------------------------------------------------- 27 28 #include "command_classes/CommandClasses.h" 29 #include "command_classes/Clock.h" 30 #include "Defs.h" 31 #include "Msg.h" 32 #include "Node.h" 33 #include "Driver.h" 34 #include "platform/Log.h" 35 36 #include "value_classes/ValueByte.h" 37 #include "value_classes/ValueList.h" 38 39 namespace OpenZWave 40 { 41 namespace Internal 42 { 43 namespace CC 44 { 45 46 enum ClockCmd 47 { 48 ClockCmd_Set = 0x04, 49 ClockCmd_Get = 0x05, 50 ClockCmd_Report = 0x06 51 }; 52 53 static char const* c_dayNames[] = 54 { "Invalid", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; 55 56 //----------------------------------------------------------------------------- 57 // <Clock::RequestState> 58 // Request current state from the device 59 //----------------------------------------------------------------------------- RequestState(uint32 const _requestFlags,uint8 const _instance,Driver::MsgQueue const _queue)60 bool Clock::RequestState(uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue) 61 { 62 if (_requestFlags & RequestFlag_Dynamic) 63 { 64 return RequestValue(_requestFlags, 0, _instance, _queue); 65 } 66 67 return false; 68 } 69 70 //----------------------------------------------------------------------------- 71 // <Clock::RequestValue> 72 // Request current value from the device 73 //----------------------------------------------------------------------------- RequestValue(uint32 const _requestFlags,uint16 const _dummy1,uint8 const _instance,Driver::MsgQueue const _queue)74 bool Clock::RequestValue(uint32 const _requestFlags, uint16 const _dummy1, // = 0 (not used) 75 uint8 const _instance, Driver::MsgQueue const _queue) 76 { 77 if (m_com.GetFlagBool(COMPAT_FLAG_GETSUPPORTED)) 78 { 79 Msg* msg = new Msg("ClockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId()); 80 msg->SetInstance(this, _instance); 81 msg->Append(GetNodeId()); 82 msg->Append(2); 83 msg->Append(GetCommandClassId()); 84 msg->Append(ClockCmd_Get); 85 msg->Append(GetDriver()->GetTransmitOptions()); 86 GetDriver()->SendMsg(msg, _queue); 87 return true; 88 } 89 else 90 { 91 Log::Write(LogLevel_Info, GetNodeId(), "ClockCmd_Get Not Supported on this node"); 92 } 93 return false; 94 } 95 96 //----------------------------------------------------------------------------- 97 // <Clock::HandleMsg> 98 // Handle a message from the Z-Wave network 99 //----------------------------------------------------------------------------- HandleMsg(uint8 const * _data,uint32 const _length,uint32 const _instance)100 bool Clock::HandleMsg(uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 101 ) 102 { 103 if (ClockCmd_Report == (ClockCmd) _data[0]) 104 { 105 uint8 day = _data[1] >> 5; 106 uint8 hour = _data[1] & 0x1f; 107 uint8 minute = _data[2]; 108 109 if (day > 7) /* size of c_dayNames */ 110 { 111 Log::Write(LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid"); 112 day = 0; 113 } 114 115 Log::Write(LogLevel_Info, GetNodeId(), "Received Clock report: %s %.2d:%.2d", c_dayNames[day], hour, minute); 116 117 if (Internal::VC::ValueList* dayValue = static_cast<Internal::VC::ValueList*>(GetValue(_instance, ValueID_Index_Clock::Day))) 118 { 119 dayValue->OnValueRefreshed(day); 120 dayValue->Release(); 121 } 122 if (Internal::VC::ValueByte* hourValue = static_cast<Internal::VC::ValueByte*>(GetValue(_instance, ValueID_Index_Clock::Hour))) 123 { 124 hourValue->OnValueRefreshed(hour); 125 hourValue->Release(); 126 } 127 if (Internal::VC::ValueByte* minuteValue = static_cast<Internal::VC::ValueByte*>(GetValue(_instance, ValueID_Index_Clock::Minute))) 128 { 129 minuteValue->OnValueRefreshed(minute); 130 minuteValue->Release(); 131 } 132 return true; 133 } 134 135 return false; 136 } 137 138 //----------------------------------------------------------------------------- 139 // <Clock::SetValue> 140 // Set a value in the Z-Wave device 141 //----------------------------------------------------------------------------- SetValue(Internal::VC::Value const & _value)142 bool Clock::SetValue(Internal::VC::Value const& _value) 143 { 144 bool ret = false; 145 146 uint8 instance = _value.GetID().GetInstance(); 147 148 Internal::VC::ValueList* dayValue = static_cast<Internal::VC::ValueList*>(GetValue(instance, ValueID_Index_Clock::Day)); 149 Internal::VC::ValueByte* hourValue = static_cast<Internal::VC::ValueByte*>(GetValue(instance, ValueID_Index_Clock::Hour)); 150 Internal::VC::ValueByte* minuteValue = static_cast<Internal::VC::ValueByte*>(GetValue(instance, ValueID_Index_Clock::Minute)); 151 152 if (dayValue && hourValue && minuteValue) 153 { 154 if (dayValue->GetItem() == NULL) 155 { 156 ret = false; 157 } 158 else 159 { 160 uint8 day = dayValue->GetItem()->m_value; 161 if (_value.GetID() == dayValue->GetID()) 162 { 163 Internal::VC::ValueList const * dayvaluetmp = static_cast<Internal::VC::ValueList const*>(&_value); 164 day = dayvaluetmp->GetItem()->m_value; 165 dayValue->OnValueRefreshed(day); 166 } 167 uint8 hour = hourValue->GetValue(); 168 if (_value.GetID() == hourValue->GetID()) 169 { 170 Internal::VC::ValueByte const * hourvaluetmp = static_cast<Internal::VC::ValueByte const*>(&_value); 171 hour = hourvaluetmp->GetValue(); 172 hourValue->OnValueRefreshed(hour); 173 } 174 uint8 minute = minuteValue->GetValue(); 175 if (_value.GetID() == minuteValue->GetID()) 176 { 177 Internal::VC::ValueByte const * minuteValuetmp = static_cast<Internal::VC::ValueByte const*>(&_value); 178 minute = minuteValuetmp->GetValue(); 179 minuteValue->OnValueRefreshed(minute); 180 } 181 182 Msg* msg = new Msg("ClockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true); 183 msg->SetInstance(this, instance); 184 msg->Append(GetNodeId()); 185 msg->Append(4); 186 msg->Append(GetCommandClassId()); 187 msg->Append(ClockCmd_Set); 188 msg->Append((day << 5) | hour); 189 msg->Append(minute); 190 msg->Append(GetDriver()->GetTransmitOptions()); 191 GetDriver()->SendMsg(msg, Driver::MsgQueue_Send); 192 ret = true; 193 } 194 } 195 196 if (dayValue != NULL) 197 { 198 dayValue->Release(); 199 } 200 if (hourValue != NULL) 201 { 202 hourValue->Release(); 203 } 204 if (minuteValue != NULL) 205 { 206 minuteValue->Release(); 207 } 208 return ret; 209 } 210 211 //----------------------------------------------------------------------------- 212 // <Clock::CreateVars> 213 // Create the values managed by this command class 214 //----------------------------------------------------------------------------- CreateVars(uint8 const _instance)215 void Clock::CreateVars(uint8 const _instance) 216 { 217 if (Node* node = GetNodeUnsafe()) 218 { 219 vector<Internal::VC::ValueList::Item> items; 220 for (int i = 1; i <= 7; ++i) 221 { 222 Internal::VC::ValueList::Item item; 223 item.m_label = c_dayNames[i]; 224 item.m_value = i; 225 items.push_back(item); 226 } 227 228 node->CreateValueList(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Day, "Day", "", false, false, 1, items, 0, 0); 229 node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Hour, "Hour", "", false, false, 12, 0); 230 node->CreateValueByte(ValueID::ValueGenre_User, GetCommandClassId(), _instance, ValueID_Index_Clock::Minute, "Minute", "", false, false, 0, 0); 231 } 232 } 233 } // namespace CC 234 } // namespace Internal 235 } // namespace OpenZWave 236