1 //-----------------------------------------------------------------------------
2 //
3 //	EnergyProduction.cpp
4 //
5 //	Implementation of the Z-Wave COMMAND_CLASS_ENERGY_PRODUCTION
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/EnergyProduction.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/ValueDecimal.h"
37 
38 using namespace OpenZWave;
39 
40 enum EnergyProductionCmd
41 {
42 	EnergyProductionCmd_Get		= 0x02,
43 	EnergyProductionCmd_Report	= 0x03
44 };
45 
46 enum
47 {
48 	EnergyProductionIndex_Instant = 0,
49 	EnergyProductionIndex_Total,
50 	EnergyProductionIndex_Today,
51 	EnergyProductionIndex_Time
52 };
53 
54 static char const* c_energyParameterNames[] =
55 {
56 	"Instant energy production",
57 	"Total energy production",
58 	"Energy production today",
59 	"Total production time"
60 };
61 
62 //-----------------------------------------------------------------------------
63 // <EnergyProduction::RequestState>
64 // Request current state from the device
65 //-----------------------------------------------------------------------------
RequestState(uint32 const _requestFlags,uint8 const _instance,Driver::MsgQueue const _queue)66 bool EnergyProduction::RequestState
67 (
68 	uint32 const _requestFlags,
69 	uint8 const _instance,
70 	Driver::MsgQueue const _queue
71 )
72 {
73 	bool request = false;
74 	if( _requestFlags & RequestFlag_Dynamic )
75 	{
76 		// Request each of the production values
77 		request |= RequestValue( _requestFlags, EnergyProductionIndex_Instant, _instance, _queue );
78 		request |= RequestValue( _requestFlags, EnergyProductionIndex_Total, _instance, _queue );
79 		request |= RequestValue( _requestFlags, EnergyProductionIndex_Today, _instance, _queue );
80 		request |= RequestValue( _requestFlags, EnergyProductionIndex_Time, _instance, _queue );
81 	}
82 
83 	return request;
84 }
85 
86 //-----------------------------------------------------------------------------
87 // <EnergyProduction::RequestValue>
88 // Request current production from the device
89 //-----------------------------------------------------------------------------
RequestValue(uint32 const _requestFlags,uint8 const _valueEnum,uint8 const _instance,Driver::MsgQueue const _queue)90 bool EnergyProduction::RequestValue
91 (
92 	uint32 const _requestFlags,
93 	uint8 const _valueEnum,		// one of EnergyProductionIndex enums
94 	uint8 const _instance,
95 	Driver::MsgQueue const _queue
96 )
97 {
98 	if (_valueEnum > EnergyProductionIndex_Time)
99 	{
100 		Log::Write (LogLevel_Warning, GetNodeId(), "RequestValue _valueEnum was greater than range. Dropping");
101 		return false;
102 	}
103 
104 	if ( IsGetSupported() )
105 	{
106 		Log::Write( LogLevel_Info, GetNodeId(), "Requesting the %s value", c_energyParameterNames[_valueEnum] );
107 		Msg* msg = new Msg( "EnergyProductionCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() );
108 		msg->SetInstance( this, _instance );
109 		msg->Append( GetNodeId() );
110 		msg->Append( 3 );
111 		msg->Append( GetCommandClassId() );
112 		msg->Append( EnergyProductionCmd_Get );
113 		msg->Append( _valueEnum );
114 		msg->Append( GetDriver()->GetTransmitOptions() );
115 		GetDriver()->SendMsg( msg, _queue );
116 		return true;
117 	} else {
118 		Log::Write(  LogLevel_Info, GetNodeId(), "EnergyProductionCmd_Get Not Supported on this node");
119 	}
120 	return false;
121 }
122 //-----------------------------------------------------------------------------
123 // <EnergyProduction::HandleMsg>
124 // Handle a message from the Z-Wave network
125 //-----------------------------------------------------------------------------
HandleMsg(uint8 const * _data,uint32 const _length,uint32 const _instance)126 bool EnergyProduction::HandleMsg
127 (
128 	uint8 const* _data,
129 	uint32 const _length,
130 	uint32 const _instance	// = 1
131 )
132 {
133 	if (EnergyProductionCmd_Report == (EnergyProductionCmd)_data[0])
134 	{
135 		uint8 scale;
136 		uint8 precision = 0;
137 		string value = ExtractValue( &_data[2], &scale, &precision );
138 		uint8 paramType = _data[1];
139 		if (paramType > 4) /* size of  c_energyParameterNames minus Invalid Entry*/
140 		{
141 			Log::Write (LogLevel_Warning, GetNodeId(), "paramType Value was greater than range. Dropping Message");
142 			return false;
143 		}
144 
145 		Log::Write( LogLevel_Info, GetNodeId(), "Received an Energy production report: %s = %s", c_energyParameterNames[_data[1]], value.c_str() );
146 		if( ValueDecimal* decimalValue = static_cast<ValueDecimal*>( GetValue( _instance, _data[1] ) ) )
147 		{
148 			decimalValue->OnValueRefreshed( value );
149 			if( decimalValue->GetPrecision() != precision )
150 			{
151 				decimalValue->SetPrecision( precision );
152 			}
153 			decimalValue->Release();
154 		}
155 		return true;
156 	}
157 
158 	return false;
159 }
160 
161 //-----------------------------------------------------------------------------
162 // <EnergyProduction::CreateVars>
163 // Create the values managed by this command class
164 //-----------------------------------------------------------------------------
CreateVars(uint8 const _instance)165 void EnergyProduction::CreateVars
166 (
167 	uint8 const _instance
168 )
169 {
170 	if( Node* node = GetNodeUnsafe() )
171 	{
172 	  	node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Instant, c_energyParameterNames[EnergyProductionIndex_Instant], "W", true, false, "0.0", 0 );
173 		node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Total, c_energyParameterNames[EnergyProductionIndex_Total], "kWh", true, false, "0.0", 0 );
174 		node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Today, c_energyParameterNames[EnergyProductionIndex_Today], "kWh", true, false, "0.0", 0 );
175 		node->CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, (uint8)EnergyProductionIndex_Time, c_energyParameterNames[EnergyProductionIndex_Time], "", true, false, "0.0", 0 );
176 	}
177 }
178 
179 
180 
181