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 using namespace OpenZWave;
40
41 enum ClockCmd
42 {
43 ClockCmd_Set = 0x04,
44 ClockCmd_Get = 0x05,
45 ClockCmd_Report = 0x06
46 };
47
48 enum
49 {
50 ClockIndex_Day = 0,
51 ClockIndex_Hour,
52 ClockIndex_Minute
53 };
54
55 static char const* c_dayNames[] =
56 {
57 "Invalid",
58 "Monday",
59 "Tuesday",
60 "Wednesday",
61 "Thursday",
62 "Friday",
63 "Saturday",
64 "Sunday"
65 };
66
67 //-----------------------------------------------------------------------------
68 // <Clock::RequestState>
69 // Request current state from the device
70 //-----------------------------------------------------------------------------
RequestState(uint32 const _requestFlags,uint8 const _instance,Driver::MsgQueue const _queue)71 bool Clock::RequestState
72 (
73 uint32 const _requestFlags,
74 uint8 const _instance,
75 Driver::MsgQueue const _queue
76 )
77 {
78 if( _requestFlags & RequestFlag_Dynamic )
79 {
80 return RequestValue( _requestFlags, 0, _instance, _queue );
81 }
82
83 return false;
84 }
85
86 //-----------------------------------------------------------------------------
87 // <Clock::RequestValue>
88 // Request current value from the device
89 //-----------------------------------------------------------------------------
RequestValue(uint32 const _requestFlags,uint8 const _dummy1,uint8 const _instance,Driver::MsgQueue const _queue)90 bool Clock::RequestValue
91 (
92 uint32 const _requestFlags,
93 uint8 const _dummy1, // = 0 (not used)
94 uint8 const _instance,
95 Driver::MsgQueue const _queue
96 )
97 {
98 if ( IsGetSupported() )
99 {
100 Msg* msg = new Msg( "ClockCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
101 msg->SetInstance( this, _instance );
102 msg->Append( GetNodeId() );
103 msg->Append( 2 );
104 msg->Append( GetCommandClassId() );
105 msg->Append( ClockCmd_Get );
106 msg->Append( GetDriver()->GetTransmitOptions() );
107 GetDriver()->SendMsg( msg, _queue );
108 return true;
109 } else {
110 Log::Write( LogLevel_Info, GetNodeId(), "ClockCmd_Get Not Supported on this node");
111 }
112 return false;
113 }
114
115 //-----------------------------------------------------------------------------
116 // <Clock::HandleMsg>
117 // Handle a message from the Z-Wave network
118 //-----------------------------------------------------------------------------
HandleMsg(uint8 const * _data,uint32 const _length,uint32 const _instance)119 bool Clock::HandleMsg
120 (
121 uint8 const* _data,
122 uint32 const _length,
123 uint32 const _instance // = 1
124 )
125 {
126 if (ClockCmd_Report == (ClockCmd)_data[0])
127 {
128 uint8 day = _data[1] >> 5;
129 uint8 hour = _data[1] & 0x1f;
130 uint8 minute = _data[2];
131
132 if (day > 7) /* size of c_dayNames */
133 {
134 Log::Write (LogLevel_Warning, GetNodeId(), "Day Value was greater than range. Setting to Invalid");
135 day = 0;
136 }
137
138 Log::Write( LogLevel_Info, GetNodeId(), "Received Clock report: %s %.2d:%.2d", c_dayNames[day], hour, minute );
139
140
141 if( ValueList* dayValue = static_cast<ValueList*>( GetValue( _instance, ClockIndex_Day ) ) )
142 {
143 dayValue->OnValueRefreshed( day );
144 dayValue->Release();
145 }
146 if( ValueByte* hourValue = static_cast<ValueByte*>( GetValue( _instance, ClockIndex_Hour ) ) )
147 {
148 hourValue->OnValueRefreshed( hour );
149 hourValue->Release();
150 }
151 if( ValueByte* minuteValue = static_cast<ValueByte*>( GetValue( _instance, ClockIndex_Minute ) ) )
152 {
153 minuteValue->OnValueRefreshed( minute );
154 minuteValue->Release();
155 }
156 return true;
157 }
158
159 return false;
160 }
161
162 //-----------------------------------------------------------------------------
163 // <Clock::SetValue>
164 // Set a value in the Z-Wave device
165 //-----------------------------------------------------------------------------
SetValue(Value const & _value)166 bool Clock::SetValue
167 (
168 Value const& _value
169 )
170 {
171 bool ret = false;
172
173 uint8 instance = _value.GetID().GetInstance();
174
175 ValueList* dayValue = static_cast<ValueList*>( GetValue( instance, ClockIndex_Day ) );
176 ValueByte* hourValue = static_cast<ValueByte*>( GetValue( instance, ClockIndex_Hour ) );
177 ValueByte* minuteValue = static_cast<ValueByte*>( GetValue( instance, ClockIndex_Minute ) );
178
179 if( dayValue && hourValue && minuteValue )
180 {
181 if (dayValue->GetItem() == NULL) {
182 ret = false;
183 } else {
184 uint8 day = dayValue->GetItem()->m_value;
185 if (_value.GetID() == dayValue->GetID()) {
186 ValueList const * dayvaluetmp = static_cast<ValueList const*>(&_value);
187 day = dayvaluetmp->GetItem()->m_value;
188 dayValue->OnValueRefreshed(day);
189 }
190 uint8 hour = hourValue->GetValue();
191 if (_value.GetID() == hourValue->GetID()) {
192 ValueByte const * hourvaluetmp = static_cast<ValueByte const*>(&_value);
193 hour = hourvaluetmp->GetValue();
194 hourValue->OnValueRefreshed(hour);
195 }
196 uint8 minute = minuteValue->GetValue();
197 if (_value.GetID() == minuteValue->GetID()) {
198 ValueByte const * minuteValuetmp = static_cast<ValueByte const*>(&_value);
199 minute = minuteValuetmp->GetValue();
200 minuteValue->OnValueRefreshed(minute);
201 }
202
203
204 Msg* msg = new Msg( "ClockCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true );
205 msg->SetInstance( this, instance );
206 msg->Append( GetNodeId() );
207 msg->Append( 4 );
208 msg->Append( GetCommandClassId() );
209 msg->Append( ClockCmd_Set );
210 msg->Append( ( day << 5 ) | hour );
211 msg->Append( minute );
212 msg->Append( GetDriver()->GetTransmitOptions() );
213 GetDriver()->SendMsg( msg, Driver::MsgQueue_Send );
214 ret = true;
215 }
216 }
217
218 if( dayValue != NULL )
219 {
220 dayValue->Release();
221 }
222 if( hourValue != NULL )
223 {
224 hourValue->Release();
225 }
226 if( minuteValue != NULL )
227 {
228 minuteValue->Release();
229 }
230 return ret;
231 }
232
233 //-----------------------------------------------------------------------------
234 // <Clock::CreateVars>
235 // Create the values managed by this command class
236 //-----------------------------------------------------------------------------
CreateVars(uint8 const _instance)237 void Clock::CreateVars
238 (
239 uint8 const _instance
240 )
241 {
242 if( Node* node = GetNodeUnsafe() )
243 {
244 vector<ValueList::Item> items;
245 for( int i=1; i<=7; ++i )
246 {
247 ValueList::Item item;
248 item.m_label = c_dayNames[i];
249 item.m_value = i;
250 items.push_back( item );
251 }
252
253 node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Day, "Day", "", false, false, 1, items, 0, 0 );
254 node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Hour, "Hour", "", false, false, 12, 0 );
255 node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, ClockIndex_Minute, "Minute", "", false, false, 0, 0 );
256 }
257 }
258