diff --git a/cpp/build/winRT/vs2015/OpenZWave.sln b/cpp/build/winRT/vs2015/OpenZWave.sln new file mode 100644 index 00000000..fc371955 --- /dev/null +++ b/cpp/build/winRT/vs2015/OpenZWave.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23103.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "OpenZWave.vcxproj", "{EB1C059F-55DA-420C-B59C-8BDB50B316DE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|ARM.ActiveCfg = Debug|ARM + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|ARM.Build.0 = Debug|ARM + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|x64.ActiveCfg = Debug|x64 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|x64.Build.0 = Debug|x64 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|x86.ActiveCfg = Debug|Win32 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Debug|x86.Build.0 = Debug|Win32 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|ARM.ActiveCfg = Release|ARM + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|ARM.Build.0 = Release|ARM + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|x64.ActiveCfg = Release|x64 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|x64.Build.0 = Release|x64 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|x86.ActiveCfg = Release|Win32 + {EB1C059F-55DA-420C-B59C-8BDB50B316DE}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/cpp/build/winRT/vs2015/OpenZWave.vcxproj b/cpp/build/winRT/vs2015/OpenZWave.vcxproj new file mode 100644 index 00000000..27a9c483 --- /dev/null +++ b/cpp/build/winRT/vs2015/OpenZWave.vcxproj @@ -0,0 +1,508 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + false + false + false + false + + + false + false + false + false + false + false + + + false + false + false + false + false + false + + + false + false + false + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + false + false + false + false + + + + {eb1c059f-55da-420c-b59c-8bdb50b316de} + WindowsRuntimeComponent + OpenZWave + OpenZWave + en-US + 14.0 + true + Windows Store + 10.0.10158.0 + 10.0.10158.0 + 10.0 + + + + DynamicLibrary + true + v140 + + + DynamicLibrary + true + v140 + + + DynamicLibrary + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + false + + + false + + + + NotUsing + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlibd;/nodefaultlib:msvcrtd;%(IgnoreSpecificDefaultLibraries) + vccorlibd.lib;msvcrtd.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + NotUsing + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlib;/nodefaultlib:msvcrt;%(IgnoreSpecificDefaultLibraries) + vccorlib.lib;msvcrt.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + NotUsing + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlibd;/nodefaultlib:msvcrtd;%(IgnoreSpecificDefaultLibraries) + vccorlibd.lib;msvcrtd.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + NotUsing + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlib;/nodefaultlib:msvcrt;%(IgnoreSpecificDefaultLibraries) + vccorlib.lib;msvcrt.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + NotUsing + _WINRT_DLL;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlibd;/nodefaultlib:msvcrtd;%(IgnoreSpecificDefaultLibraries) + vccorlibd.lib;msvcrtd.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + NotUsing + _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) + pch.h + $(IntDir)pch.pch + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + /bigobj %(AdditionalOptions) + 28204 + ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) + + + Console + false + /nodefaultlib:vccorlib;/nodefaultlib:msvcrt;%(IgnoreSpecificDefaultLibraries) + vccorlib.lib;msvcrt.lib;%(AdditionalDependencies) + + + del ..\winversion.cpp +CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" +exit 0 + + + + + + \ No newline at end of file diff --git a/cpp/build/winRT/vs2015/OpenZWave.vcxproj.filters b/cpp/build/winRT/vs2015/OpenZWave.vcxproj.filters new file mode 100644 index 00000000..393df8e6 --- /dev/null +++ b/cpp/build/winRT/vs2015/OpenZWave.vcxproj.filters @@ -0,0 +1,661 @@ + + + + + e956b6cc-8fce-4fea-9862-30a92e4c457f + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {145f7034-a6f4-4a79-a798-ec5e16cd924a} + + + {e4999648-71a8-4ac9-97eb-1a198cfc37b1} + + + {04041ba9-0609-4b13-88e8-16fef5a26dc2} + + + {f6b7ce9f-9ded-49ba-a823-3f655b53b2a9} + + + {8548f516-7114-410f-991d-5e2ca865b687} + + + {6fe8adf3-4f69-45b0-964d-731edd44b3b4} + + + {5c9fb2dd-7c7f-4a12-9760-bca3a3d36675} + + + + + AES + + + AES + + + AES + + + AES + + + AES + + + AES + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + TinyXML + + + TinyXML + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + + + AES + + + AES + + + AES + + + AES + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Command Classes + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Main + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + Value Classes + + + TinyXML + + + TinyXML + + + TinyXML + + + TinyXML + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Platform\WinRT + + + Main + + + \ No newline at end of file diff --git a/cpp/src/Driver.cpp b/cpp/src/Driver.cpp index 6a2f7658..8b38cf17 100644 --- a/cpp/src/Driver.cpp +++ b/cpp/src/Driver.cpp @@ -37,7 +37,11 @@ #include "platform/Event.h" #include "platform/Mutex.h" #include "platform/SerialController.h" -#include "platform/HidController.h" +#ifdef _WINRT_DLL +#include "platform/winRT/HidControllerWinRT.h" +#else +#include "platform/HidController.h" +#endif #include "platform/Thread.h" #include "platform/Log.h" #include "platform/TimeStamp.h" @@ -137,6 +141,7 @@ Driver::Driver ControllerInterface const& _interface ): m_driverThread( new Thread( "driver" ) ), +m_initMutex(new Mutex()), m_exit( false ), m_init( false ), m_awakeNodesQueried( false ), @@ -266,7 +271,9 @@ Driver::~Driver // The order of the statements below has been achieved by mitigating freed memory //references using a memory allocator checker. Do not rearrange unless you are //certain memory won't be referenced out of order. --Greg Satz, April 2010 + m_initMutex->Lock(); m_exit = true; + m_initMutex->Unlock(); m_pollThread->Stop(); m_pollThread->Release(); @@ -279,6 +286,8 @@ Driver::~Driver m_controller->Close(); m_controller->Release(); + m_initMutex->Release(); + if( m_currentMsg != NULL ) { RemoveCurrentMsg(); @@ -526,6 +535,14 @@ bool Driver::Init uint32 _attempts ) { + m_initMutex->Lock(); + + if (m_exit) + { + m_initMutex->Unlock(); + return false; + } + m_Controller_nodeId = -1; m_waitingForAck = false; @@ -535,6 +552,7 @@ bool Driver::Init if( !m_controller->Open( m_controllerPath ) ) { Log::Write( LogLevel_Warning, "WARNING: Failed to init the controller (attempt %d)", _attempts ); + m_initMutex->Unlock(); return false; } @@ -553,6 +571,8 @@ bool Driver::Init //msg->Append( 0xff ); //SendMsg( msg ); + m_initMutex->Unlock(); + // Init successful return true; } @@ -1214,7 +1234,20 @@ bool Driver::WriteMsg } } else { Log::Write( LogLevel_Info, nodeId, "Sending (%s) message (%sCallback ID=0x%.2x, Expected Reply=0x%.2x) - %s", c_sendQueueNames[m_currentMsgQueueSource], attemptsstr.c_str(), m_expectedCallbackId, m_expectedReply, m_currentMsg->GetAsString().c_str() ); - m_controller->Write( m_currentMsg->GetBuffer(), m_currentMsg->GetLength() ); + uint32 bytesWritten = m_controller->Write(m_currentMsg->GetBuffer(), m_currentMsg->GetLength()); + + if (bytesWritten == 0) + { + //0 will be returned when the port is closed or something bad happened + //so send notification + Notification* notification = new Notification(Notification::Type_DriverFailed); + notification->SetHomeAndNodeIds(m_homeId, m_currentMsg->GetTargetNodeId()); + QueueNotification(notification); + NotifyWatchers(); + + m_driverThread->Stop(); + return false; + } } m_writeCnt++; diff --git a/cpp/src/Driver.h b/cpp/src/Driver.h index 78620399..3c82e5a1 100644 --- a/cpp/src/Driver.h +++ b/cpp/src/Driver.h @@ -149,6 +149,7 @@ namespace OpenZWave void RemoveQueues( uint8 const _nodeId ); Thread* m_driverThread; /**< Thread for reading from the Z-Wave controller, and for creating and managing the other threads for sending, polling etc. */ + Mutex* m_initMutex; /**< Mutex to ensure proper ordering of initialization/deinitialization */ bool m_exit; /**< Flag that is set when the application is exiting. */ bool m_init; /**< Set to true once the driver has been initialised */ bool m_awakeNodesQueried; /**< Set to true once the driver has polled all awake nodes */ @@ -479,7 +480,7 @@ OPENZWAVE_EXPORT_WARNINGS_ON * Controller States. * States reported via the callback handler passed into the BeginControllerCommand method. * \see Manager::BeginControllerCommand - */ + */ enum ControllerState { ControllerState_Normal = 0, /**< No command in progress. */ @@ -658,7 +659,7 @@ OPENZWAVE_EXPORT_WARNINGS_ON m_queryStage(Node::QueryStage_None), m_retry(false), m_cci(NULL) - {} + {} bool operator == ( MsgQueueItem const& _other )const { diff --git a/cpp/src/Options.cpp b/cpp/src/Options.cpp index 0da60d29..0be4ecd1 100644 --- a/cpp/src/Options.cpp +++ b/cpp/src/Options.cpp @@ -129,6 +129,10 @@ Options* Options::Create s_instance->AddOptionString( "SecurityStrategy", "SUPPORTED", false); // Should we encrypt CC's that are available via both clear text and Security CC? s_instance->AddOptionString( "CustomSecuredCC", "0x62,0x4c,0x63", false); // What List of Custom CC should we always encrypt if SecurityStrategy is CUSTOM s_instance->AddOptionBool( "EnforceSecureReception", true); // if we recieve a clear text message for a CC that is Secured, should we drop the message + +#if defined _WINRT_DLL + s_instance->AddOptionInt( "ThreadTerminateTimeout", -1); // Since threads cannot be terminated in WinRT, Thread::Terminate will simply wait for them to exit on there own +#endif } return s_instance; diff --git a/cpp/src/command_classes/TimeParameters.cpp b/cpp/src/command_classes/TimeParameters.cpp index 62fdd4ee..89dec40e 100644 --- a/cpp/src/command_classes/TimeParameters.cpp +++ b/cpp/src/command_classes/TimeParameters.cpp @@ -1,236 +1,243 @@ -//----------------------------------------------------------------------------- -// -// TimeParameters.cpp -// -// Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS -// -// Copyright (c) 2014 Justin Hammond -// -// 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 "command_classes/CommandClasses.h" -#include "command_classes/TimeParameters.h" -#include "Defs.h" -#include "Msg.h" -#include "Node.h" -#include "Driver.h" -#include "platform/Log.h" - -#include "value_classes/ValueButton.h" -#include "value_classes/ValueString.h" - -using namespace OpenZWave; - -enum TimeParametersCmd -{ - TimeParametersCmd_Set = 0x01, - TimeParametersCmd_Get = 0x02, - TimeParametersCmd_Report = 0x03 -}; - -enum -{ - TimeParametersIndex_Date = 0, - TimeParametersIndex_Time, - TimeParametersIndex_Set, - TimeParametersIndex_Refresh -}; - - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -TimeParameters::TimeParameters -( - uint32 const _homeId, - uint8 const _nodeId -): - CommandClass( _homeId, _nodeId ) -{ - SetStaticRequest( StaticRequest_Values ); -} - - -//----------------------------------------------------------------------------- -// -// Request current state from the device -//----------------------------------------------------------------------------- -bool TimeParameters::RequestState -( - uint32 const _requestFlags, - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) - { - return RequestValue( _requestFlags, 0, _instance, _queue ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// -// Request current value from the device -//----------------------------------------------------------------------------- -bool TimeParameters::RequestValue -( - uint32 const _requestFlags, - uint8 const _dummy1, // = 0 (not used) - uint8 const _instance, - Driver::MsgQueue const _queue -) -{ - if ( IsGetSupported() ) - { - Msg* msg = new Msg( "TimeParametersCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, _instance ); - msg->Append( GetNodeId() ); - msg->Append( 2 ); - msg->Append( GetCommandClassId() ); - msg->Append( TimeParametersCmd_Get ); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, _queue ); - return true; - } else { - Log::Write( LogLevel_Info, GetNodeId(), "TimeParametersCmd_Get Not Supported on this node"); - } - return false; -} - -//----------------------------------------------------------------------------- -// -// Handle a message from the Z-Wave network -//----------------------------------------------------------------------------- -bool TimeParameters::HandleMsg -( - uint8 const* _data, - uint32 const _length, - uint32 const _instance // = 1 -) -{ - if (TimeParametersCmd_Report == (TimeParametersCmd)_data[0]) - { - uint16 year = (_data[1] << 8) + (_data[2] & 0xFF); - uint8 month = (_data[3] & 0x0F); - uint8 day = (_data[4] & 0x1F); - uint8 hour = (_data[5] & 0x1F); - uint8 minute = (_data[6] & 0x3F); - uint8 second = (_data[7] & 0x3F); - - Log::Write( LogLevel_Info, GetNodeId(), "Received TimeParameters report: %02d/%02d/%04d %02d:%02d:%02d", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second); - if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Date ) ) ) - { - char msg[512]; - snprintf(msg, sizeof(msg), "%02d/%02d/%04d", (int)day, (int)month, (int)year); - value->OnValueRefreshed( msg ); - value->Release(); - } - if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Time ) ) ) - { - char msg[512]; - snprintf(msg, sizeof(msg), "%02d:%02d:%02d", (int)hour, (int)minute, (int)second); - value->OnValueRefreshed( msg ); - value->Release(); - } - ClearStaticRequest( StaticRequest_Values ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// -// Set a value in the Z-Wave device -//----------------------------------------------------------------------------- -bool TimeParameters::SetValue -( - Value const& _value -) -{ - bool ret = false; - - uint8 instance = _value.GetID().GetInstance(); - - if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Set) ) - { - time_t rawtime; - struct tm *timeinfo; - time(&rawtime); - timeinfo = localtime(&rawtime); - Msg* msg = new Msg( "TimeParametersCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); - msg->SetInstance( this, instance ); - msg->Append( GetNodeId() ); - msg->Append( 9 ); - msg->Append( GetCommandClassId() ); - msg->Append( TimeParametersCmd_Set ); - /* Year 1 */ - msg->Append( ((timeinfo->tm_year + 1900)>> 8) & 0xFF); - /* Year 2 */ - msg->Append( ((timeinfo->tm_year + 1900) & 0xFF)); - /* Month */ - msg->Append( (timeinfo->tm_mon & 0x0F)+1); - /* Day */ - msg->Append( (timeinfo->tm_mday & 0x1F)); - /* Hour */ - msg->Append( (timeinfo->tm_hour & 0x1F)); - /* Minute */ - msg->Append( (timeinfo->tm_min & 0x3F)); - /* Second */ - msg->Append( (timeinfo->tm_sec & 0x3F)); - msg->Append( GetDriver()->GetTransmitOptions() ); - GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); - - - /* Refresh after we send updated date/time */ - SetStaticRequest( StaticRequest_Values ); - ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); - } - if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Refresh) ) - { - SetStaticRequest( StaticRequest_Values ); - ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); - } - - return ret; -} - -//----------------------------------------------------------------------------- -// -// Create the values managed by this command class -//----------------------------------------------------------------------------- -void TimeParameters::CreateVars -( - uint8 const _instance -) -{ - if( Node* node = GetNodeUnsafe() ) - { - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Date, "Date", "", true, false, "", 0 ); - node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Time, "Time", "", true, false, "", 0 ); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Set, "Set Date/Time", 0); - node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Refresh, "Refresh Date/Time", 0); - - } -} +//----------------------------------------------------------------------------- +// +// TimeParameters.cpp +// +// Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS +// +// Copyright (c) 2014 Justin Hammond +// +// 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 "command_classes/CommandClasses.h" +#include "command_classes/TimeParameters.h" +#include "Defs.h" +#include "Msg.h" +#include "Node.h" +#include "Driver.h" +#include "platform/Log.h" + +#include "value_classes/ValueButton.h" +#include "value_classes/ValueString.h" + +using namespace OpenZWave; + +enum TimeParametersCmd +{ + TimeParametersCmd_Set = 0x01, + TimeParametersCmd_Get = 0x02, + TimeParametersCmd_Report = 0x03 +}; + +enum +{ + TimeParametersIndex_Date = 0, + TimeParametersIndex_Time, + TimeParametersIndex_Set, + TimeParametersIndex_Refresh +}; + + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +TimeParameters::TimeParameters +( + uint32 const _homeId, + uint8 const _nodeId +): + CommandClass( _homeId, _nodeId ) +{ + SetStaticRequest( StaticRequest_Values ); +} + + +//----------------------------------------------------------------------------- +// +// Request current state from the device +//----------------------------------------------------------------------------- +bool TimeParameters::RequestState +( + uint32 const _requestFlags, + uint8 const _instance, + Driver::MsgQueue const _queue +) +{ + if( ( _requestFlags & RequestFlag_Static ) && HasStaticRequest( StaticRequest_Values ) ) + { + return RequestValue( _requestFlags, 0, _instance, _queue ); + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// Request current value from the device +//----------------------------------------------------------------------------- +bool TimeParameters::RequestValue +( + uint32 const _requestFlags, + uint8 const _dummy1, // = 0 (not used) + uint8 const _instance, + Driver::MsgQueue const _queue +) +{ + if ( IsGetSupported() ) + { + Msg* msg = new Msg( "TimeParametersCmd_Get", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); + msg->SetInstance( this, _instance ); + msg->Append( GetNodeId() ); + msg->Append( 2 ); + msg->Append( GetCommandClassId() ); + msg->Append( TimeParametersCmd_Get ); + msg->Append( GetDriver()->GetTransmitOptions() ); + GetDriver()->SendMsg( msg, _queue ); + return true; + } else { + Log::Write( LogLevel_Info, GetNodeId(), "TimeParametersCmd_Get Not Supported on this node"); + } + return false; +} + +//----------------------------------------------------------------------------- +// +// Handle a message from the Z-Wave network +//----------------------------------------------------------------------------- +bool TimeParameters::HandleMsg +( + uint8 const* _data, + uint32 const _length, + uint32 const _instance // = 1 +) +{ + if (TimeParametersCmd_Report == (TimeParametersCmd)_data[0]) + { + uint16 year = (_data[1] << 8) + (_data[2] & 0xFF); + uint8 month = (_data[3] & 0x0F); + uint8 day = (_data[4] & 0x1F); + uint8 hour = (_data[5] & 0x1F); + uint8 minute = (_data[6] & 0x3F); + uint8 second = (_data[7] & 0x3F); + + Log::Write( LogLevel_Info, GetNodeId(), "Received TimeParameters report: %02d/%02d/%04d %02d:%02d:%02d", (int)day, (int)month, (int)year, (int)hour, (int)minute, (int)second); + if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Date ) ) ) + { + char msg[512]; + snprintf(msg, sizeof(msg), "%02d/%02d/%04d", (int)day, (int)month, (int)year); + value->OnValueRefreshed( msg ); + value->Release(); + } + if( ValueString* value = static_cast( GetValue( _instance, TimeParametersIndex_Time ) ) ) + { + char msg[512]; + snprintf(msg, sizeof(msg), "%02d:%02d:%02d", (int)hour, (int)minute, (int)second); + value->OnValueRefreshed( msg ); + value->Release(); + } + ClearStaticRequest( StaticRequest_Values ); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// Set a value in the Z-Wave device +//----------------------------------------------------------------------------- +bool TimeParameters::SetValue +( + Value const& _value +) +{ + bool ret = false; + + uint8 instance = _value.GetID().GetInstance(); + + if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Set) ) + { + time_t rawtime; + struct tm *timeinfo; + time(&rawtime); +#ifdef WINAPI_FAMILY_APP +#pragma warning(push) +#pragma warning(disable:4996) +#endif + timeinfo = localtime(&rawtime); +#ifdef WINAPI_FAMILY_APP +#pragma warning(pop) +#endif + Msg* msg = new Msg( "TimeParametersCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true, true, FUNC_ID_APPLICATION_COMMAND_HANDLER, GetCommandClassId() ); + msg->SetInstance( this, instance ); + msg->Append( GetNodeId() ); + msg->Append( 9 ); + msg->Append( GetCommandClassId() ); + msg->Append( TimeParametersCmd_Set ); + /* Year 1 */ + msg->Append( ((timeinfo->tm_year + 1900)>> 8) & 0xFF); + /* Year 2 */ + msg->Append( ((timeinfo->tm_year + 1900) & 0xFF)); + /* Month */ + msg->Append( (timeinfo->tm_mon & 0x0F)+1); + /* Day */ + msg->Append( (timeinfo->tm_mday & 0x1F)); + /* Hour */ + msg->Append( (timeinfo->tm_hour & 0x1F)); + /* Minute */ + msg->Append( (timeinfo->tm_min & 0x3F)); + /* Second */ + msg->Append( (timeinfo->tm_sec & 0x3F)); + msg->Append( GetDriver()->GetTransmitOptions() ); + GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); + + + /* Refresh after we send updated date/time */ + SetStaticRequest( StaticRequest_Values ); + ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); + } + if ( (ValueID::ValueType_Button == _value.GetID().GetType()) && (_value.GetID().GetIndex() == TimeParametersIndex_Refresh) ) + { + SetStaticRequest( StaticRequest_Values ); + ret = RequestValue( RequestFlag_Static, 0, instance, Driver::MsgQueue_Query ); + } + + return ret; +} + +//----------------------------------------------------------------------------- +// +// Create the values managed by this command class +//----------------------------------------------------------------------------- +void TimeParameters::CreateVars +( + uint8 const _instance +) +{ + if( Node* node = GetNodeUnsafe() ) + { + node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Date, "Date", "", true, false, "", 0 ); + node->CreateValueString( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Time, "Time", "", true, false, "", 0 ); + node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Set, "Set Date/Time", 0); + node->CreateValueButton( ValueID::ValueGenre_System, GetCommandClassId(), _instance, TimeParametersIndex_Refresh, "Refresh Date/Time", 0); + + } +} diff --git a/cpp/src/platform/Event.cpp b/cpp/src/platform/Event.cpp index 3f4ad4ab..93476bdc 100644 --- a/cpp/src/platform/Event.cpp +++ b/cpp/src/platform/Event.cpp @@ -1,107 +1,109 @@ -//----------------------------------------------------------------------------- -// -// Event.cpp -// -// Cross-platform event -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/Event.h" - -#ifdef WIN32 -#include "platform/windows/EventImpl.h" // Platform-specific implementation of an event -#else -#include "platform/unix/EventImpl.h" // Platform-specific implementation of an event -#endif - -using namespace OpenZWave; - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -Event::Event -( -): - m_pImpl( new EventImpl() ) -{ -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -Event::~Event -( -) -{ - delete m_pImpl; -} - -//----------------------------------------------------------------------------- -// -// Set the event to signalled -//----------------------------------------------------------------------------- -void Event::Set -( -) -{ - m_pImpl->Set(); - Notify(); // Notify any watchers that the event is now set -} - -//----------------------------------------------------------------------------- -// -// Set the event to not signalled -//----------------------------------------------------------------------------- -void Event::Reset -( -) -{ - m_pImpl->Reset(); -} - -//----------------------------------------------------------------------------- -// -// Test whether the event is set -//----------------------------------------------------------------------------- -bool Event::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} - -//----------------------------------------------------------------------------- -// -// Wait for the event to become signalled -//----------------------------------------------------------------------------- -bool Event::Wait -( - int32 const _timeout -) -{ - return m_pImpl->Wait( _timeout ); -} - - +//----------------------------------------------------------------------------- +// +// Event.cpp +// +// Cross-platform event +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Event.h" + +#ifdef WIN32 +#include "platform/windows/EventImpl.h" // Platform-specific implementation of an event +#elif defined _WINRT_DLL +#include "platform/winRT/EventImpl.h" // Platform-specific implementation of an event +#else +#include "platform/unix/EventImpl.h" // Platform-specific implementation of an event +#endif + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +Event::Event +( +): + m_pImpl( new EventImpl() ) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +Event::~Event +( +) +{ + delete m_pImpl; +} + +//----------------------------------------------------------------------------- +// +// Set the event to signalled +//----------------------------------------------------------------------------- +void Event::Set +( +) +{ + m_pImpl->Set(); + Notify(); // Notify any watchers that the event is now set +} + +//----------------------------------------------------------------------------- +// +// Set the event to not signalled +//----------------------------------------------------------------------------- +void Event::Reset +( +) +{ + m_pImpl->Reset(); +} + +//----------------------------------------------------------------------------- +// +// Test whether the event is set +//----------------------------------------------------------------------------- +bool Event::IsSignalled +( +) +{ + return m_pImpl->IsSignalled(); +} + +//----------------------------------------------------------------------------- +// +// Wait for the event to become signalled +//----------------------------------------------------------------------------- +bool Event::Wait +( + int32 const _timeout +) +{ + return m_pImpl->Wait( _timeout ); +} + + diff --git a/cpp/src/platform/FileOps.cpp b/cpp/src/platform/FileOps.cpp index 12bcb6e5..9f47ff50 100644 --- a/cpp/src/platform/FileOps.cpp +++ b/cpp/src/platform/FileOps.cpp @@ -1,105 +1,107 @@ -//----------------------------------------------------------------------------- -// -// FileOps.cpp -// -// Cross-platform File Operations -// -// Copyright (c) 2012 Greg Satz -// All rights reserved. -// -// 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 "platform/FileOps.h" - -#ifdef WIN32 -#include "platform/windows/FileOpsImpl.h" // Platform-specific implementation of a File Operations -#else -#include "platform/unix/FileOpsImpl.h" // Platform-specific implementation of a File Operations -#endif - -using namespace OpenZWave; - -FileOps* FileOps::s_instance = NULL; -FileOpsImpl* FileOps::m_pImpl = NULL; - -//----------------------------------------------------------------------------- -// -// Static creation of the singleton -//----------------------------------------------------------------------------- -FileOps* FileOps::Create -( -) -{ - if( s_instance == NULL ) - { - s_instance = new FileOps(); - } - return s_instance; -} - -//----------------------------------------------------------------------------- -// -// Static method to destroy the fileops singleton. -//----------------------------------------------------------------------------- -void FileOps::Destroy -( -) -{ - delete s_instance; - s_instance = NULL; -} - -//----------------------------------------------------------------------------- -// -// Static method to check for existance of a folder -//----------------------------------------------------------------------------- -bool FileOps::FolderExists -( - const string &_folderName -) -{ - if( s_instance != NULL ) - { - return s_instance->m_pImpl->FolderExists( _folderName ); - } - return false; -} - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -FileOps::FileOps -( -) -{ - m_pImpl = new FileOpsImpl(); -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -FileOps::~FileOps -( -) -{ - delete m_pImpl; -} +//----------------------------------------------------------------------------- +// +// FileOps.cpp +// +// Cross-platform File Operations +// +// Copyright (c) 2012 Greg Satz +// All rights reserved. +// +// 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 "platform/FileOps.h" + +#ifdef WIN32 +#include "platform/windows/FileOpsImpl.h" // Platform-specific implementation of a File Operations +#elif defined _WINRT_DLL +#include "platform/winRT/FileOpsImpl.h" // Platform-specific implementation of a File Operations +#else +#include "platform/unix/FileOpsImpl.h" // Platform-specific implementation of a File Operations +#endif + +using namespace OpenZWave; + +FileOps* FileOps::s_instance = NULL; +FileOpsImpl* FileOps::m_pImpl = NULL; + +//----------------------------------------------------------------------------- +// +// Static creation of the singleton +//----------------------------------------------------------------------------- +FileOps* FileOps::Create +( +) +{ + if( s_instance == NULL ) + { + s_instance = new FileOps(); + } + return s_instance; +} + +//----------------------------------------------------------------------------- +// +// Static method to destroy the fileops singleton. +//----------------------------------------------------------------------------- +void FileOps::Destroy +( +) +{ + delete s_instance; + s_instance = NULL; +} + +//----------------------------------------------------------------------------- +// +// Static method to check for existance of a folder +//----------------------------------------------------------------------------- +bool FileOps::FolderExists +( + const string &_folderName +) +{ + if( s_instance != NULL ) + { + return s_instance->m_pImpl->FolderExists( _folderName ); + } + return false; +} + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +FileOps::FileOps +( +) +{ + m_pImpl = new FileOpsImpl(); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +FileOps::~FileOps +( +) +{ + delete m_pImpl; +} diff --git a/cpp/src/platform/Log.cpp b/cpp/src/platform/Log.cpp index 7f5e11ec..49ca9c38 100644 --- a/cpp/src/platform/Log.cpp +++ b/cpp/src/platform/Log.cpp @@ -1,339 +1,341 @@ -//----------------------------------------------------------------------------- -// -// Log.cpp -// -// Cross-platform message and error logging -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/Mutex.h" -#include "platform/Log.h" - -#ifdef WIN32 -#include "platform/windows/LogImpl.h" // Platform-specific implementation of a log -#else -#include "platform/unix/LogImpl.h" // Platform-specific implementation of a log -#endif - - -using namespace OpenZWave; - -char const *OpenZWave::LogLevelString[] = -{ - "Invalid", /**< Invalid Log Level Status - Used to Indicate error from Importing bad Options.xml */ - "None", /**< LogLevel_None Disable all logging */ - "Always", /**< LogLevel_Always These messages should always be shown */ - "Fatal", /**< LogLevel_Fatal A likely fatal issue in the library */ - "Error", /**< LogLevel_Error A serious issue with the library or the network */ - "Warning", /**< LogLevel_Warning A minor issue from which the library should be able to recover */ - "Alert", /**< LogLevel_Alert Something unexpected by the library about which the controlling application should be aware */ - "Info", /**< LogLevel_Info Everything's working fine...these messages provide streamlined feedback on each message */ - "Detail", /**< LogLevel_Detail Detailed information on the progress of each message */ - "Debug", /**< LogLevel_Debug Very detailed information on progress that will create a huge log file quickly - But this level (as others) can be queued and sent to the log only on an error or warning */ - "StreamDetail", /**< LogLevel_StreamDetail Will include low-level byte transfers from controller to buffer to application and back */ - "Internal" /**< LogLevel_Internal Used only within the log class (uses existing timestamp, etc.) */ -}; - - - -Log* Log::s_instance = NULL; -i_LogImpl* Log::m_pImpl = NULL; -static bool s_dologging; - -//----------------------------------------------------------------------------- -// -// Static creation of the singleton -//----------------------------------------------------------------------------- -Log* Log::Create -( - string const& _filename, - bool const _bAppend, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -) -{ - if( NULL == s_instance ) - { - s_instance = new Log( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); - s_dologging = true; // default logging to true so no change to what people experience now +//----------------------------------------------------------------------------- +// +// Log.cpp +// +// Cross-platform message and error logging +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Mutex.h" +#include "platform/Log.h" + +#ifdef WIN32 +#include "platform/windows/LogImpl.h" // Platform-specific implementation of a log +#elif defined _WINRT_DLL +#include "platform/winRT/LogImpl.h" // Platform-specific implementation of a log +#else +#include "platform/unix/LogImpl.h" // Platform-specific implementation of a log +#endif + + +using namespace OpenZWave; + +char const *OpenZWave::LogLevelString[] = +{ + "Invalid", /**< Invalid Log Level Status - Used to Indicate error from Importing bad Options.xml */ + "None", /**< LogLevel_None Disable all logging */ + "Always", /**< LogLevel_Always These messages should always be shown */ + "Fatal", /**< LogLevel_Fatal A likely fatal issue in the library */ + "Error", /**< LogLevel_Error A serious issue with the library or the network */ + "Warning", /**< LogLevel_Warning A minor issue from which the library should be able to recover */ + "Alert", /**< LogLevel_Alert Something unexpected by the library about which the controlling application should be aware */ + "Info", /**< LogLevel_Info Everything's working fine...these messages provide streamlined feedback on each message */ + "Detail", /**< LogLevel_Detail Detailed information on the progress of each message */ + "Debug", /**< LogLevel_Debug Very detailed information on progress that will create a huge log file quickly + But this level (as others) can be queued and sent to the log only on an error or warning */ + "StreamDetail", /**< LogLevel_StreamDetail Will include low-level byte transfers from controller to buffer to application and back */ + "Internal" /**< LogLevel_Internal Used only within the log class (uses existing timestamp, etc.) */ +}; + + + +Log* Log::s_instance = NULL; +i_LogImpl* Log::m_pImpl = NULL; +static bool s_dologging; + +//----------------------------------------------------------------------------- +// +// Static creation of the singleton +//----------------------------------------------------------------------------- +Log* Log::Create +( + string const& _filename, + bool const _bAppend, + bool const _bConsoleOutput, + LogLevel const _saveLevel, + LogLevel const _queueLevel, + LogLevel const _dumpTrigger +) +{ + if( NULL == s_instance ) + { + s_instance = new Log( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); + s_dologging = true; // default logging to true so no change to what people experience now } else { Log::Destroy(); s_instance = new Log( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); - s_dologging = true; // default logging to true so no change to what people experience now - } - - return s_instance; -} - -//----------------------------------------------------------------------------- -// -// Static creation of the singleton -//----------------------------------------------------------------------------- -/* It isn't clear this is ever called or used. If no one complains, consider - deleting this code in April 2012. -Log* Log::Create -( - i_LogImpl *LogClass -) -{ - if (NULL == s_instance ) - { - s_instance = new Log( "" ); - s_dologging = true; - } - SetLoggingClass( LogClass ); - return s_instance; -} -*/ - -//----------------------------------------------------------------------------- -// -// Static method to destroy the logging singleton. -//----------------------------------------------------------------------------- -void Log::Destroy -( -) -{ - delete s_instance; - s_instance = NULL; -} - -//----------------------------------------------------------------------------- -// -// Set log class -//----------------------------------------------------------------------------- -bool Log::SetLoggingClass -( - i_LogImpl *LogClass -) -{ - delete m_pImpl; - m_pImpl = LogClass; - return true; -} - -//----------------------------------------------------------------------------- -// -// Set flag to actually write to log or skip it (legacy version) -// If logging is enabled, the default log detail settings will be used -// Write to file/screen LogLevel_Detail -// Save in queue for errors LogLevel_Debug -// Trigger for dumping queue LogLevel_Warning -// Console output? Yes -// Append to an existing log? No (overwrite) -//----------------------------------------------------------------------------- -void Log::SetLoggingState -( - bool _dologging -) -{ - bool prevLogging = s_dologging; - s_dologging = _dologging; - - if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); -} - -//----------------------------------------------------------------------------- -// -// Set flag to actually write to log or skip it -//----------------------------------------------------------------------------- -void Log::SetLoggingState -( - LogLevel _saveLevel, - LogLevel _queueLevel, - LogLevel _dumpTrigger -) -{ - // parameter checking: - // _queueLevel cannot be less than or equal to _saveLevel (where lower ordinals are more severe conditions) - // _dumpTrigger cannot be greater than or equal to _queueLevel - if( _queueLevel <= _saveLevel ) - Log::Write( LogLevel_Warning, "Only lower priority messages may be queued for error-driven display." ); - if( _dumpTrigger >= _queueLevel ) - Log::Write( LogLevel_Warning, "The trigger for dumping queued messages must be a higher-priority message than the level that is queued." ); - - bool prevLogging = s_dologging; - // s_dologging is true if any messages are to be saved in file or queue - if( (_saveLevel > LogLevel_Always) || - (_queueLevel > LogLevel_Always) ) - { - s_dologging = true; - } - else - { - s_dologging = false; - } - - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->SetLoggingState( _saveLevel, _queueLevel, _dumpTrigger ); - s_instance->m_logMutex->Unlock(); - } - - if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); -} - -//----------------------------------------------------------------------------- -// -// Return a flag to indicate whether logging is enabled -//----------------------------------------------------------------------------- -bool Log::GetLoggingState -( -) -{ - return s_dologging; -} - -//----------------------------------------------------------------------------- -// -// Write to the log -//----------------------------------------------------------------------------- -void Log::Write -( - LogLevel _level, - char const* _format, - ... -) -{ - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - s_instance->m_logMutex->Lock(); // double locks if recursive - va_list args; - va_start( args, _format ); - s_instance->m_pImpl->Write( _level, 0, _format, args ); - va_end( args ); - s_instance->m_logMutex->Unlock(); - } -} - -//----------------------------------------------------------------------------- -// -// Write to the log -//----------------------------------------------------------------------------- -void Log::Write -( - LogLevel _level, - uint8 const _nodeId, - char const* _format, - ... -) -{ - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - if( _level != LogLevel_Internal ) - s_instance->m_logMutex->Lock(); - va_list args; - va_start( args, _format ); - s_instance->m_pImpl->Write( _level, _nodeId, _format, args ); - va_end( args ); - if( _level != LogLevel_Internal ) - s_instance->m_logMutex->Unlock(); - } -} - -//----------------------------------------------------------------------------- -// -// Send queued messages to the log (and empty the queue) -//----------------------------------------------------------------------------- -void Log::QueueDump -( -) -{ - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->QueueDump(); - s_instance->m_logMutex->Unlock(); - } -} - -//----------------------------------------------------------------------------- -// -// Empty the queued message queue -//----------------------------------------------------------------------------- -void Log::QueueClear -( -) -{ - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->QueueClear(); - s_instance->m_logMutex->Unlock(); - } -} - -//----------------------------------------------------------------------------- -// -// Change the name of the log file (will start writing a new file) -//----------------------------------------------------------------------------- -void Log::SetLogFileName -( - const string &_filename -) -{ - if( s_instance && s_dologging && s_instance->m_pImpl ) - { - s_instance->m_logMutex->Lock(); - s_instance->m_pImpl->SetLogFileName( _filename ); - s_instance->m_logMutex->Unlock(); - } -} - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -Log::Log -( - string const& _filename, - bool const _bAppend, - bool const _bConsoleOutput, - LogLevel const _saveLevel, - LogLevel const _queueLevel, - LogLevel const _dumpTrigger -): - m_logMutex( new Mutex() ) -{ - if (NULL == m_pImpl) - m_pImpl = new LogImpl( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -Log::~Log -( -) -{ - m_logMutex->Release(); - delete m_pImpl; - m_pImpl = NULL; -} + s_dologging = true; // default logging to true so no change to what people experience now + } + + return s_instance; +} + +//----------------------------------------------------------------------------- +// +// Static creation of the singleton +//----------------------------------------------------------------------------- +/* It isn't clear this is ever called or used. If no one complains, consider + deleting this code in April 2012. +Log* Log::Create +( + i_LogImpl *LogClass +) +{ + if (NULL == s_instance ) + { + s_instance = new Log( "" ); + s_dologging = true; + } + SetLoggingClass( LogClass ); + return s_instance; +} +*/ + +//----------------------------------------------------------------------------- +// +// Static method to destroy the logging singleton. +//----------------------------------------------------------------------------- +void Log::Destroy +( +) +{ + delete s_instance; + s_instance = NULL; +} + +//----------------------------------------------------------------------------- +// +// Set log class +//----------------------------------------------------------------------------- +bool Log::SetLoggingClass +( + i_LogImpl *LogClass +) +{ + delete m_pImpl; + m_pImpl = LogClass; + return true; +} + +//----------------------------------------------------------------------------- +// +// Set flag to actually write to log or skip it (legacy version) +// If logging is enabled, the default log detail settings will be used +// Write to file/screen LogLevel_Detail +// Save in queue for errors LogLevel_Debug +// Trigger for dumping queue LogLevel_Warning +// Console output? Yes +// Append to an existing log? No (overwrite) +//----------------------------------------------------------------------------- +void Log::SetLoggingState +( + bool _dologging +) +{ + bool prevLogging = s_dologging; + s_dologging = _dologging; + + if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); +} + +//----------------------------------------------------------------------------- +// +// Set flag to actually write to log or skip it +//----------------------------------------------------------------------------- +void Log::SetLoggingState +( + LogLevel _saveLevel, + LogLevel _queueLevel, + LogLevel _dumpTrigger +) +{ + // parameter checking: + // _queueLevel cannot be less than or equal to _saveLevel (where lower ordinals are more severe conditions) + // _dumpTrigger cannot be greater than or equal to _queueLevel + if( _queueLevel <= _saveLevel ) + Log::Write( LogLevel_Warning, "Only lower priority messages may be queued for error-driven display." ); + if( _dumpTrigger >= _queueLevel ) + Log::Write( LogLevel_Warning, "The trigger for dumping queued messages must be a higher-priority message than the level that is queued." ); + + bool prevLogging = s_dologging; + // s_dologging is true if any messages are to be saved in file or queue + if( (_saveLevel > LogLevel_Always) || + (_queueLevel > LogLevel_Always) ) + { + s_dologging = true; + } + else + { + s_dologging = false; + } + + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + s_instance->m_logMutex->Lock(); + s_instance->m_pImpl->SetLoggingState( _saveLevel, _queueLevel, _dumpTrigger ); + s_instance->m_logMutex->Unlock(); + } + + if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); +} + +//----------------------------------------------------------------------------- +// +// Return a flag to indicate whether logging is enabled +//----------------------------------------------------------------------------- +bool Log::GetLoggingState +( +) +{ + return s_dologging; +} + +//----------------------------------------------------------------------------- +// +// Write to the log +//----------------------------------------------------------------------------- +void Log::Write +( + LogLevel _level, + char const* _format, + ... +) +{ + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + s_instance->m_logMutex->Lock(); // double locks if recursive + va_list args; + va_start( args, _format ); + s_instance->m_pImpl->Write( _level, 0, _format, args ); + va_end( args ); + s_instance->m_logMutex->Unlock(); + } +} + +//----------------------------------------------------------------------------- +// +// Write to the log +//----------------------------------------------------------------------------- +void Log::Write +( + LogLevel _level, + uint8 const _nodeId, + char const* _format, + ... +) +{ + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + if( _level != LogLevel_Internal ) + s_instance->m_logMutex->Lock(); + va_list args; + va_start( args, _format ); + s_instance->m_pImpl->Write( _level, _nodeId, _format, args ); + va_end( args ); + if( _level != LogLevel_Internal ) + s_instance->m_logMutex->Unlock(); + } +} + +//----------------------------------------------------------------------------- +// +// Send queued messages to the log (and empty the queue) +//----------------------------------------------------------------------------- +void Log::QueueDump +( +) +{ + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + s_instance->m_logMutex->Lock(); + s_instance->m_pImpl->QueueDump(); + s_instance->m_logMutex->Unlock(); + } +} + +//----------------------------------------------------------------------------- +// +// Empty the queued message queue +//----------------------------------------------------------------------------- +void Log::QueueClear +( +) +{ + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + s_instance->m_logMutex->Lock(); + s_instance->m_pImpl->QueueClear(); + s_instance->m_logMutex->Unlock(); + } +} + +//----------------------------------------------------------------------------- +// +// Change the name of the log file (will start writing a new file) +//----------------------------------------------------------------------------- +void Log::SetLogFileName +( + const string &_filename +) +{ + if( s_instance && s_dologging && s_instance->m_pImpl ) + { + s_instance->m_logMutex->Lock(); + s_instance->m_pImpl->SetLogFileName( _filename ); + s_instance->m_logMutex->Unlock(); + } +} + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +Log::Log +( + string const& _filename, + bool const _bAppend, + bool const _bConsoleOutput, + LogLevel const _saveLevel, + LogLevel const _queueLevel, + LogLevel const _dumpTrigger +): + m_logMutex( new Mutex() ) +{ + if (NULL == m_pImpl) + m_pImpl = new LogImpl( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +Log::~Log +( +) +{ + m_logMutex->Release(); + delete m_pImpl; + m_pImpl = NULL; +} diff --git a/cpp/src/platform/Mutex.cpp b/cpp/src/platform/Mutex.cpp index 3fad4609..8e42f011 100644 --- a/cpp/src/platform/Mutex.cpp +++ b/cpp/src/platform/Mutex.cpp @@ -1,101 +1,103 @@ -//----------------------------------------------------------------------------- -// -// Mutex.cpp -// -// Cross-platform mutex -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/Mutex.h" - -#ifdef WIN32 -#include "platform/windows/MutexImpl.h" // Platform-specific implementation of a mutex -#else -#include "platform/unix/MutexImpl.h" // Platform-specific implementation of a mutex -#endif - - -using namespace OpenZWave; - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -Mutex::Mutex -( -): - m_pImpl( new MutexImpl() ) -{ -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -Mutex::~Mutex -( -) -{ - delete m_pImpl; -} - -//----------------------------------------------------------------------------- -// -// Lock the mutex -//----------------------------------------------------------------------------- -bool Mutex::Lock -( - bool const _bWait // = true; -) -{ - return m_pImpl->Lock( _bWait ); -} - -//----------------------------------------------------------------------------- -// -// Release our lock on the mutex -//----------------------------------------------------------------------------- -void Mutex::Unlock -( -) -{ - m_pImpl->Unlock(); - - if( IsSignalled() ) - { - // The mutex has no owners, so notify the watchers - Notify(); - } -} - -//----------------------------------------------------------------------------- -// -// Test whether the event is set -//----------------------------------------------------------------------------- -bool Mutex::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} - +//----------------------------------------------------------------------------- +// +// Mutex.cpp +// +// Cross-platform mutex +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Mutex.h" + +#ifdef WIN32 +#include "platform/windows/MutexImpl.h" // Platform-specific implementation of a mutex +#elif defined _WINRT_DLL +#include "platform/winRT/MutexImpl.h" // Platform-specific implementation of a mutex +#else +#include "platform/unix/MutexImpl.h" // Platform-specific implementation of a mutex +#endif + + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +Mutex::Mutex +( +): + m_pImpl( new MutexImpl() ) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +Mutex::~Mutex +( +) +{ + delete m_pImpl; +} + +//----------------------------------------------------------------------------- +// +// Lock the mutex +//----------------------------------------------------------------------------- +bool Mutex::Lock +( + bool const _bWait // = true; +) +{ + return m_pImpl->Lock( _bWait ); +} + +//----------------------------------------------------------------------------- +// +// Release our lock on the mutex +//----------------------------------------------------------------------------- +void Mutex::Unlock +( +) +{ + m_pImpl->Unlock(); + + if( IsSignalled() ) + { + // The mutex has no owners, so notify the watchers + Notify(); + } +} + +//----------------------------------------------------------------------------- +// +// Test whether the event is set +//----------------------------------------------------------------------------- +bool Mutex::IsSignalled +( +) +{ + return m_pImpl->IsSignalled(); +} + diff --git a/cpp/src/platform/SerialController.cpp b/cpp/src/platform/SerialController.cpp index 99d2c832..08375056 100644 --- a/cpp/src/platform/SerialController.cpp +++ b/cpp/src/platform/SerialController.cpp @@ -1,185 +1,187 @@ -//----------------------------------------------------------------------------- -// -// SerialController.h -// -// Cross-platform serial port handler -// -// Copyright (c) 2010 Jason Frazier -// -// 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 "Msg.h" -#include "platform/Event.h" -#include "platform/Thread.h" -#include "platform/SerialController.h" -#include "platform/Log.h" - -#ifdef WIN32 -#include "platform/windows/SerialControllerImpl.h" // Platform-specific implementation of a serial port -#else -#include "platform/unix/SerialControllerImpl.h" // Platform-specific implementation of a serial port -#endif - -using namespace OpenZWave; - - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -SerialController::SerialController -( -): - m_baud ( 115200 ), - m_parity ( SerialController::Parity_None ), - m_stopBits ( SerialController::StopBits_One ), - m_bOpen( false ) -{ - m_pImpl = new SerialControllerImpl( this ); -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -SerialController::~SerialController -( -) -{ - delete m_pImpl; -} - -//----------------------------------------------------------------------------- -// -// Set the serial port baud rate. -// The serial port must be closed for the setting to be accepted. -//----------------------------------------------------------------------------- -bool SerialController::SetBaud -( - uint32 const _baud -) -{ - if( m_bOpen ) - { - return false; - } - - m_baud = _baud; - return true; -} - -//----------------------------------------------------------------------------- -// -// Set the serial port parity. -// The serial port must be closed for the setting to be accepted. -//----------------------------------------------------------------------------- -bool SerialController::SetParity -( - Parity const _parity -) -{ - if( m_bOpen ) - { - return false; - } - - m_parity = _parity; - return true; -} - -//----------------------------------------------------------------------------- -// -// Set the serial port stop bits. -// The serial port must be closed for the setting to be accepted. -//----------------------------------------------------------------------------- -bool SerialController::SetStopBits -( - StopBits const _stopBits -) -{ - if( m_bOpen ) - { - return false; - } - - m_stopBits = _stopBits; - return true; -} - -//----------------------------------------------------------------------------- -// -// Open and configure a serial port -//----------------------------------------------------------------------------- -bool SerialController::Open -( - string const& _serialControllerName -) -{ - if( m_bOpen ) - { - return false; - } - - m_serialControllerName = _serialControllerName; - m_bOpen = m_pImpl->Open(); - return m_bOpen; -} - -//----------------------------------------------------------------------------- -// -// Close a serial port -//----------------------------------------------------------------------------- -bool SerialController::Close -( -) -{ - if( !m_bOpen ) - { - return false; - } - - m_pImpl->Close(); - m_bOpen = false; - return true; -} - -//----------------------------------------------------------------------------- -// -// Write data to an open serial port -//----------------------------------------------------------------------------- -uint32 SerialController::Write -( - uint8* _buffer, - uint32 _length -) -{ - if( !m_bOpen ) - { - return 0; - } - - Log::Write( LogLevel_StreamDetail, " SerialController::Write (sent to controller)" ); - LogData(_buffer, _length, " Write: "); - - return( m_pImpl->Write( _buffer, _length ) ); -} - - - +//----------------------------------------------------------------------------- +// +// SerialController.h +// +// Cross-platform serial port handler +// +// Copyright (c) 2010 Jason Frazier +// +// 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 "Msg.h" +#include "platform/Event.h" +#include "platform/Thread.h" +#include "platform/SerialController.h" +#include "platform/Log.h" + +#ifdef WIN32 +#include "platform/windows/SerialControllerImpl.h" // Platform-specific implementation of a serial port +#elif defined _WINRT_DLL +#include "platform/winRT/SerialControllerImpl.h" // Platform-specific implementation of a serial port +#else +#include "platform/unix/SerialControllerImpl.h" // Platform-specific implementation of a serial port +#endif + +using namespace OpenZWave; + + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +SerialController::SerialController +( +): + m_baud ( 115200 ), + m_parity ( SerialController::Parity_None ), + m_stopBits ( SerialController::StopBits_One ), + m_bOpen( false ) +{ + m_pImpl = new SerialControllerImpl( this ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +SerialController::~SerialController +( +) +{ + delete m_pImpl; +} + +//----------------------------------------------------------------------------- +// +// Set the serial port baud rate. +// The serial port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool SerialController::SetBaud +( + uint32 const _baud +) +{ + if( m_bOpen ) + { + return false; + } + + m_baud = _baud; + return true; +} + +//----------------------------------------------------------------------------- +// +// Set the serial port parity. +// The serial port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool SerialController::SetParity +( + Parity const _parity +) +{ + if( m_bOpen ) + { + return false; + } + + m_parity = _parity; + return true; +} + +//----------------------------------------------------------------------------- +// +// Set the serial port stop bits. +// The serial port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool SerialController::SetStopBits +( + StopBits const _stopBits +) +{ + if( m_bOpen ) + { + return false; + } + + m_stopBits = _stopBits; + return true; +} + +//----------------------------------------------------------------------------- +// +// Open and configure a serial port +//----------------------------------------------------------------------------- +bool SerialController::Open +( + string const& _serialControllerName +) +{ + if( m_bOpen ) + { + return false; + } + + m_serialControllerName = _serialControllerName; + m_bOpen = m_pImpl->Open(); + return m_bOpen; +} + +//----------------------------------------------------------------------------- +// +// Close a serial port +//----------------------------------------------------------------------------- +bool SerialController::Close +( +) +{ + if( !m_bOpen ) + { + return false; + } + + m_pImpl->Close(); + m_bOpen = false; + return true; +} + +//----------------------------------------------------------------------------- +// +// Write data to an open serial port +//----------------------------------------------------------------------------- +uint32 SerialController::Write +( + uint8* _buffer, + uint32 _length +) +{ + if( !m_bOpen ) + { + return 0; + } + + Log::Write( LogLevel_StreamDetail, " SerialController::Write (sent to controller)" ); + LogData(_buffer, _length, " Write: "); + + return( m_pImpl->Write( _buffer, _length ) ); +} + + + diff --git a/cpp/src/platform/Thread.cpp b/cpp/src/platform/Thread.cpp index 1aaf440d..a727ecb0 100644 --- a/cpp/src/platform/Thread.cpp +++ b/cpp/src/platform/Thread.cpp @@ -1,123 +1,125 @@ -//----------------------------------------------------------------------------- -// -// Thread.cpp -// -// Cross-platform threads -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/Event.h" -#include "platform/Thread.h" - -#ifdef WIN32 -#include "platform/windows/ThreadImpl.h" // Platform-specific implementation of a thread -#else -#include "platform/unix/ThreadImpl.h" // Platform-specific implementation of a thread -#endif - -using namespace OpenZWave; - - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -Thread::Thread -( - string const& _name -) -{ - m_exitEvent = new Event(); - m_pImpl = new ThreadImpl( this, _name ); -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -Thread::~Thread -( -) -{ - delete m_pImpl; - m_exitEvent->Release(); -} - -//----------------------------------------------------------------------------- -// -// Start a function running on this thread -//----------------------------------------------------------------------------- -bool Thread::Start -( - pfnThreadProc_t _pfnThreadProc, - void* _context -) -{ - return( m_pImpl->Start( _pfnThreadProc, m_exitEvent, _context ) ); -} - -//----------------------------------------------------------------------------- -// -// Stop a function running on this thread -//----------------------------------------------------------------------------- -bool Thread::Stop -( -) -{ - int32 timeout = 2000; // Give the thread 2 seconds to exit - m_exitEvent->Set(); - - if( Wait::Single( this, timeout ) < 0 ) - { - // Timed out - m_pImpl->Terminate(); - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// -// Causes the thread to sleep for the specified number of milliseconds. -//----------------------------------------------------------------------------- -void Thread::Sleep -( - uint32 _milliseconds -) -{ - return( m_pImpl->Sleep( _milliseconds ) ); -} - -//----------------------------------------------------------------------------- -// -// Test whether the event is set -//----------------------------------------------------------------------------- -bool Thread::IsSignalled -( -) -{ - return m_pImpl->IsSignalled(); -} - - +//----------------------------------------------------------------------------- +// +// Thread.cpp +// +// Cross-platform threads +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Event.h" +#include "platform/Thread.h" + +#ifdef WIN32 +#include "platform/windows/ThreadImpl.h" // Platform-specific implementation of a thread +#elif defined _WINRT_DLL +#include "platform/winRT/ThreadImpl.h" // Platform-specific implementation of a thread +#else +#include "platform/unix/ThreadImpl.h" // Platform-specific implementation of a thread +#endif + +using namespace OpenZWave; + + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +Thread::Thread +( + string const& _name +) +{ + m_exitEvent = new Event(); + m_pImpl = new ThreadImpl( this, _name ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +Thread::~Thread +( +) +{ + delete m_pImpl; + m_exitEvent->Release(); +} + +//----------------------------------------------------------------------------- +// +// Start a function running on this thread +//----------------------------------------------------------------------------- +bool Thread::Start +( + pfnThreadProc_t _pfnThreadProc, + void* _context +) +{ + return( m_pImpl->Start( _pfnThreadProc, m_exitEvent, _context ) ); +} + +//----------------------------------------------------------------------------- +// +// Stop a function running on this thread +//----------------------------------------------------------------------------- +bool Thread::Stop +( +) +{ + int32 timeout = 2000; // Give the thread 2 seconds to exit + m_exitEvent->Set(); + + if( Wait::Single( this, timeout ) < 0 ) + { + // Timed out + m_pImpl->Terminate(); + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// +// Causes the thread to sleep for the specified number of milliseconds. +//----------------------------------------------------------------------------- +void Thread::Sleep +( + uint32 _milliseconds +) +{ + return( m_pImpl->Sleep( _milliseconds ) ); +} + +//----------------------------------------------------------------------------- +// +// Test whether the event is set +//----------------------------------------------------------------------------- +bool Thread::IsSignalled +( +) +{ + return m_pImpl->IsSignalled(); +} + + diff --git a/cpp/src/platform/TimeStamp.cpp b/cpp/src/platform/TimeStamp.cpp index afb875cb..e224696c 100644 --- a/cpp/src/platform/TimeStamp.cpp +++ b/cpp/src/platform/TimeStamp.cpp @@ -1,106 +1,108 @@ -//----------------------------------------------------------------------------- -// -// TimeStamp.h -// -// Cross-platform TimeStamp -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/TimeStamp.h" - -#ifdef WIN32 -#include "platform/windows/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp -#else -#include "platform/unix/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp -#endif - -using namespace OpenZWave; - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -TimeStamp::TimeStamp -( -): - m_pImpl( new TimeStampImpl() ) -{ -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -TimeStamp::~TimeStamp -( -) -{ - delete m_pImpl; -} - -//----------------------------------------------------------------------------- -// -// Sets the timestamp to now, plus an offset in milliseconds -//----------------------------------------------------------------------------- -void TimeStamp::SetTime -( - int32 _milliseconds // = 0 -) -{ - m_pImpl->SetTime( _milliseconds ); -} - -//----------------------------------------------------------------------------- -// -// Gets the difference between now and the timestamp time in milliseconds -//----------------------------------------------------------------------------- -int32 TimeStamp::TimeRemaining -( -) -{ - return m_pImpl->TimeRemaining(); -} - -//----------------------------------------------------------------------------- -// -// Return object as a string -//----------------------------------------------------------------------------- -string TimeStamp::GetAsString -( -) -{ - return m_pImpl->GetAsString(); -} -//----------------------------------------------------------------------------- -// -// Overload the subtract operator to get the difference between two -// timestamps in milliseconds -//----------------------------------------------------------------------------- -int32 TimeStamp::operator- -( - TimeStamp const& _other -) -{ - return (int32)(m_pImpl - _other.m_pImpl); -} +//----------------------------------------------------------------------------- +// +// TimeStamp.h +// +// Cross-platform TimeStamp +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/TimeStamp.h" + +#ifdef WIN32 +#include "platform/windows/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp +#elif defined _WINRT_DLL +#include "platform/winRT/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp +#else +#include "platform/unix/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp +#endif + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +TimeStamp::TimeStamp +( +): + m_pImpl( new TimeStampImpl() ) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +TimeStamp::~TimeStamp +( +) +{ + delete m_pImpl; +} + +//----------------------------------------------------------------------------- +// +// Sets the timestamp to now, plus an offset in milliseconds +//----------------------------------------------------------------------------- +void TimeStamp::SetTime +( + int32 _milliseconds // = 0 +) +{ + m_pImpl->SetTime( _milliseconds ); +} + +//----------------------------------------------------------------------------- +// +// Gets the difference between now and the timestamp time in milliseconds +//----------------------------------------------------------------------------- +int32 TimeStamp::TimeRemaining +( +) +{ + return m_pImpl->TimeRemaining(); +} + +//----------------------------------------------------------------------------- +// +// Return object as a string +//----------------------------------------------------------------------------- +string TimeStamp::GetAsString +( +) +{ + return m_pImpl->GetAsString(); +} +//----------------------------------------------------------------------------- +// +// Overload the subtract operator to get the difference between two +// timestamps in milliseconds +//----------------------------------------------------------------------------- +int32 TimeStamp::operator- +( + TimeStamp const& _other +) +{ + return (int32)(m_pImpl - _other.m_pImpl); +} diff --git a/cpp/src/platform/Wait.cpp b/cpp/src/platform/Wait.cpp index 120e78c6..7cb87dcc 100644 --- a/cpp/src/platform/Wait.cpp +++ b/cpp/src/platform/Wait.cpp @@ -1,182 +1,184 @@ -//----------------------------------------------------------------------------- -// -// Wait.cpp -// -// Base class for objects we want to be able to wait for. -// -// Copyright (c) 2010 Mal Lansell -// All rights reserved. -// -// 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 "Defs.h" -#include "platform/Wait.h" -#include "platform/Event.h" -#include "platform/Log.h" - -#ifdef WIN32 -#include "platform/windows/WaitImpl.h" // Platform-specific implementation of a Wait object -#else -#include "platform/unix/WaitImpl.h" // Platform-specific implementation of a Wait object -#endif - -using namespace OpenZWave; - -void WaitMultipleCallback( void* _context ); - -//----------------------------------------------------------------------------- -// -// Constructor -//----------------------------------------------------------------------------- -Wait::Wait -( -) -{ - m_pImpl = new WaitImpl( this ); -} - -//----------------------------------------------------------------------------- -// -// Destructor -//----------------------------------------------------------------------------- -Wait::~Wait -( -) -{ - delete m_pImpl; -} - -//----------------------------------------------------------------------------- -// -// Add a watcher to our object. -//----------------------------------------------------------------------------- -void Wait::AddWatcher -( - pfnWaitNotification_t _callback, - void* _context -) -{ - if( !_callback ) - { - assert(0); - return; - } - - // Add a ref so our object cannot disappear while being watched - AddRef(); - - // Add the watcher (platform specific code required here for thread safety) - m_pImpl->AddWatcher( _callback, _context ); -} - -//----------------------------------------------------------------------------- -// -// Remove a watcher from our object. -//----------------------------------------------------------------------------- -void Wait::RemoveWatcher -( - pfnWaitNotification_t _callback, - void* _context -) -{ - if( m_pImpl->RemoveWatcher( _callback, _context ) ) - { - Release(); - } -} - -//----------------------------------------------------------------------------- -// -// Notify all the watchers that the object has become signalled -//----------------------------------------------------------------------------- -void Wait::Notify -( -) -{ - m_pImpl->Notify(); -} - -//----------------------------------------------------------------------------- -// -// Wait for one of multiple objects to become signalled. -//----------------------------------------------------------------------------- -int32 Wait::Multiple -( - Wait** _objects, - uint32 _numObjects, - int32 _timeout // = -1 -) -{ - uint32 i; - - // Create an event that will be set when any of the objects in the list becomes signalled. - Event* waitEvent = new Event(); - - // Add a watcher to each object in the list, passing in the event as the context. - for( i=0; i<_numObjects; ++i ) - { - _objects[i]->AddWatcher( WaitMultipleCallback, waitEvent ); - } - - int32 res = -1; // Default to timeout result - string str = ""; - if( waitEvent->Wait( _timeout ) ) - { - // An object was signalled. Run through the list - // and see which one it was. - for( i=0; i<_numObjects; ++i ) - { - if( _objects[i]->IsSignalled() ) - { - if( res == -1 ) - res = (int32)i; - char buf[15]; - snprintf(buf, sizeof(buf), "%d, ", i); - str += buf; - } - } - } - //Log::Write( LogLevel_Debug, "Wait::Multiple res=%d num=%d >%s", res, _numObjects, str.c_str() ); - - // Remove the watchers - for( i=0; i<_numObjects; ++i ) - { - _objects[i]->RemoveWatcher( WaitMultipleCallback, waitEvent ); - } - - // We're done with the event now - waitEvent->Release(); - return res; -} - - -//----------------------------------------------------------------------------- -// -// Callback handler for the watchers added during WaitImpl::Multiple -//----------------------------------------------------------------------------- -void WaitMultipleCallback -( - void* _context -) -{ - Event* waitEvent = (Event*)_context; - waitEvent->Set(); -} - +//----------------------------------------------------------------------------- +// +// Wait.cpp +// +// Base class for objects we want to be able to wait for. +// +// Copyright (c) 2010 Mal Lansell +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Wait.h" +#include "platform/Event.h" +#include "platform/Log.h" + +#ifdef WIN32 +#include "platform/windows/WaitImpl.h" // Platform-specific implementation of a Wait object +#elif defined _WINRT_DLL +#include "platform/winRT/WaitImpl.h" // Platform-specific implementation of a Wait object +#else +#include "platform/unix/WaitImpl.h" // Platform-specific implementation of a Wait object +#endif + +using namespace OpenZWave; + +void WaitMultipleCallback( void* _context ); + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +Wait::Wait +( +) +{ + m_pImpl = new WaitImpl( this ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +Wait::~Wait +( +) +{ + delete m_pImpl; +} + +//----------------------------------------------------------------------------- +// +// Add a watcher to our object. +//----------------------------------------------------------------------------- +void Wait::AddWatcher +( + pfnWaitNotification_t _callback, + void* _context +) +{ + if( !_callback ) + { + assert(0); + return; + } + + // Add a ref so our object cannot disappear while being watched + AddRef(); + + // Add the watcher (platform specific code required here for thread safety) + m_pImpl->AddWatcher( _callback, _context ); +} + +//----------------------------------------------------------------------------- +// +// Remove a watcher from our object. +//----------------------------------------------------------------------------- +void Wait::RemoveWatcher +( + pfnWaitNotification_t _callback, + void* _context +) +{ + if( m_pImpl->RemoveWatcher( _callback, _context ) ) + { + Release(); + } +} + +//----------------------------------------------------------------------------- +// +// Notify all the watchers that the object has become signalled +//----------------------------------------------------------------------------- +void Wait::Notify +( +) +{ + m_pImpl->Notify(); +} + +//----------------------------------------------------------------------------- +// +// Wait for one of multiple objects to become signalled. +//----------------------------------------------------------------------------- +int32 Wait::Multiple +( + Wait** _objects, + uint32 _numObjects, + int32 _timeout // = -1 +) +{ + uint32 i; + + // Create an event that will be set when any of the objects in the list becomes signalled. + Event* waitEvent = new Event(); + + // Add a watcher to each object in the list, passing in the event as the context. + for( i=0; i<_numObjects; ++i ) + { + _objects[i]->AddWatcher( WaitMultipleCallback, waitEvent ); + } + + int32 res = -1; // Default to timeout result + string str = ""; + if( waitEvent->Wait( _timeout ) ) + { + // An object was signalled. Run through the list + // and see which one it was. + for( i=0; i<_numObjects; ++i ) + { + if( _objects[i]->IsSignalled() ) + { + if( res == -1 ) + res = (int32)i; + char buf[15]; + snprintf(buf, sizeof(buf), "%d, ", i); + str += buf; + } + } + } + //Log::Write( LogLevel_Debug, "Wait::Multiple res=%d num=%d >%s", res, _numObjects, str.c_str() ); + + // Remove the watchers + for( i=0; i<_numObjects; ++i ) + { + _objects[i]->RemoveWatcher( WaitMultipleCallback, waitEvent ); + } + + // We're done with the event now + waitEvent->Release(); + return res; +} + + +//----------------------------------------------------------------------------- +// +// Callback handler for the watchers added during WaitImpl::Multiple +//----------------------------------------------------------------------------- +void WaitMultipleCallback +( + void* _context +) +{ + Event* waitEvent = (Event*)_context; + waitEvent->Set(); +} + diff --git a/cpp/src/platform/winRT/EventImpl.cpp b/cpp/src/platform/winRT/EventImpl.cpp new file mode 100644 index 00000000..94bc076e --- /dev/null +++ b/cpp/src/platform/winRT/EventImpl.cpp @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// +// EventImpl.cpp +// +// WinRT implementation of a cross-platform event +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "EventImpl.h" + +using namespace OpenZWave; + + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +EventImpl::EventImpl +( +) +{ + // Create a manual reset event + m_hEvent = ::CreateEventEx( NULL, NULL, CREATE_EVENT_MANUAL_RESET, SYNCHRONIZE | EVENT_MODIFY_STATE ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +EventImpl::~EventImpl +( +) +{ + ::CloseHandle( m_hEvent ); +} + +//----------------------------------------------------------------------------- +// +// Set the event to signalled +//----------------------------------------------------------------------------- +void EventImpl::Set +( +) +{ + ::SetEvent( m_hEvent ); +} + +//----------------------------------------------------------------------------- +// +// Set the event to not signalled +//----------------------------------------------------------------------------- +void EventImpl::Reset +( +) +{ + ::ResetEvent( m_hEvent ); +} + +//----------------------------------------------------------------------------- +// +// Test whether the event is set +//----------------------------------------------------------------------------- +bool EventImpl::IsSignalled +( +) +{ + return( WAIT_OBJECT_0 == WaitForSingleObjectEx( m_hEvent, 0, FALSE) ); +} + +//----------------------------------------------------------------------------- +// +// Wait for the event to become signalled +//----------------------------------------------------------------------------- +bool EventImpl::Wait +( + int32 const _timeout +) +{ + return( WAIT_TIMEOUT != ::WaitForSingleObjectEx( m_hEvent, (DWORD)_timeout, FALSE ) ); +} diff --git a/cpp/src/platform/winRT/EventImpl.h b/cpp/src/platform/winRT/EventImpl.h new file mode 100644 index 00000000..14f10e23 --- /dev/null +++ b/cpp/src/platform/winRT/EventImpl.h @@ -0,0 +1,60 @@ +//----------------------------------------------------------------------------- +// +// EventImpl.h +// +// WinRT implementation of a cross-platform event +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _EventImpl_H +#define _EventImpl_H + +#include +#include "Defs.h" + +namespace OpenZWave +{ + /** \brief Windows-specific implementation of the Event class. + */ + class EventImpl + { + private: + friend class Event; + friend class SocketImpl; + friend class Wait; + + EventImpl(); + ~EventImpl(); + + void Set(); + void Reset(); + + bool Wait( int32 _timeout ); // The wait method is to be used only by the Wait::Multiple method + bool IsSignalled(); + + HANDLE m_hEvent; + }; + +} // namespace OpenZWave + +#endif //_EventImpl_H + diff --git a/cpp/src/platform/winRT/FileOpsImpl.cpp b/cpp/src/platform/winRT/FileOpsImpl.cpp new file mode 100644 index 00000000..cb723bf5 --- /dev/null +++ b/cpp/src/platform/winRT/FileOpsImpl.cpp @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// +// FileOpsImpl.cpp +// +// WinRT implementation of file operations +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "FileOpsImpl.h" + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +FileOpsImpl::FileOpsImpl +( +) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +FileOpsImpl::~FileOpsImpl +( +) +{ +} + +//----------------------------------------------------------------------------- +// +// Determine if a folder exists and is accessible by the calling App +//----------------------------------------------------------------------------- +bool FileOpsImpl::FolderExists( + const string &_folderName +) +{ + WIN32_FILE_ATTRIBUTE_DATA fad = { 0 }; + wstring wFolderName(_folderName.begin(), _folderName.end()); + + if (0 == GetFileAttributesEx(wFolderName.c_str(), GetFileExInfoStandard, &fad)) + return false; + + return (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? true: false; +} diff --git a/cpp/src/platform/winRT/FileOpsImpl.h b/cpp/src/platform/winRT/FileOpsImpl.h new file mode 100644 index 00000000..a8e49445 --- /dev/null +++ b/cpp/src/platform/winRT/FileOpsImpl.h @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// +// FileOpsImpl.h +// +// WinRT implementation of file operations +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _FileOpsImpl_H +#define _FileOpsImpl_H + +#include +#include +#include "Defs.h" +#include "platform/FileOps.h" + +namespace OpenZWave +{ + class FileOpsImpl + { + friend class FileOps; + + private: + FileOpsImpl(); + ~FileOpsImpl(); + + bool FolderExists( const string &_filename ); + }; + +} // namespace OpenZWave + +#endif //_FileOpsImpl_H + diff --git a/cpp/src/platform/winRT/HidControllerWinRT.cpp b/cpp/src/platform/winRT/HidControllerWinRT.cpp new file mode 100644 index 00000000..68342d40 --- /dev/null +++ b/cpp/src/platform/winRT/HidControllerWinRT.cpp @@ -0,0 +1,276 @@ +//----------------------------------------------------------------------------- +// +// HidControllerWinRT.cpp +// +// WinRT implementation of a HidController +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "HidControllerWinRT.h" +#include "platform/Log.h" + +#include +#include + +using namespace Windows::Devices::Enumeration; +using namespace Windows::Devices::HumanInterfaceDevice; +using namespace Windows::Devices::Usb; +using namespace Windows::Foundation; +using namespace Windows::Storage::Streams; +using namespace Platform; +using namespace Concurrency; +using namespace OpenZWave; + +#define AQS_FORMAT L"System.Devices.InterfaceClassGuid:=\"{4D1E55B2-F16F-11CF-88CB-001111000030}\" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.Hid.VendorId:=%04d AND System.DeviceInterface.Hid.ProductId:=%04d" +#define AQS_LENGTH 300 + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +HidController::HidController() : + m_vendorId(0x1b5f), // Wayne Dalton + m_productId(0x01), // ControlThink ThinkStick + m_serialNumber(""), + m_hidControllerName(""), + m_bOpen(false) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +HidController::~HidController() +{ + if (m_device != nullptr) + { + m_device->InputReportReceived -= m_inputReportEventToken; + } +} + +//----------------------------------------------------------------------------- +// +// Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool HidController::SetVendorId +( +uint32 const _vendorId +) +{ + if (m_bOpen) + { + return false; + } + + m_vendorId = _vendorId; + return true; +} + +//----------------------------------------------------------------------------- +// +// Set the USB product ID search value. The HID port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool HidController::SetProductId (uint32 const _productId) +{ + if (m_bOpen) + { + return false; + } + + m_productId = _productId; + return true; +} + +//----------------------------------------------------------------------------- +// +// Set the USB serial number search value. The HID port must be closed for the setting to be accepted. +//----------------------------------------------------------------------------- +bool HidController::SetSerialNumber (string const& _serialNumber) +{ + if (m_bOpen) + { + return false; + } + + m_serialNumber = _serialNumber; + return true; +} + +//----------------------------------------------------------------------------- +// +// Open and configure a HID port +//----------------------------------------------------------------------------- +bool HidController::Open(string const& _hidControllerName) +{ + if (m_bOpen) + { + return false; + } + + m_hidControllerName = _hidControllerName; + + bool success = false; + try + { + create_task(Init()).then([&success, this](bool initResult) + { + success = initResult; + if (success && m_device != nullptr) + { + m_inputReportEventToken = m_device->InputReportReceived += ref new TypedEventHandler + ([this](HidDevice ^sender, HidInputReportReceivedEventArgs ^args) + { + auto reader = DataReader::FromBuffer(args->Report->Data); + uint32 bufferSize = reader->UnconsumedBufferLength; + std::vector data(bufferSize); + + if (!data.empty()) + { + reader->ReadBytes(::Platform::ArrayReference(&data[0], bufferSize)); + Put(&data[0], bufferSize); + } + }); + } + + }).wait(); + } + catch (Platform::Exception^ ex) + { + } + + return success; +} + +//----------------------------------------------------------------------------- +// +// Close a HID port +//----------------------------------------------------------------------------- +bool HidController::Close() +{ + if (m_device != nullptr) + { + m_device->InputReportReceived -= m_inputReportEventToken; + delete m_device; + m_device = nullptr; + } + return true; +} + +//----------------------------------------------------------------------------- +// +// Open the HID port +//----------------------------------------------------------------------------- +task HidController::Init() +{ + // Yields the same as API above w/o the usage page and usage Id filters + wchar_t buffer[AQS_LENGTH]; + swprintf_s(buffer, AQS_FORMAT, m_vendorId, m_productId); + auto selector = ref new String(buffer); + + return create_task(Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(selector)) + .then([this](DeviceInformationCollection ^ devices) -> String ^ + { + String ^deviceId = L""; + for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) + { + // Not sure how to differentiate when there are multiple things returned. + // Just return first matching ID for now + deviceId = iterator->Current->Id; + break; + } + return deviceId; + + }).then([this](String ^deviceId) -> IAsyncOperation ^ + { + return HidDevice::FromIdAsync(deviceId, Windows::Storage::FileAccessMode::Read); + + }).then([this](task deviceTask) -> bool + { + try + { + m_device = deviceTask.get(); + + if (m_device == nullptr) + { + return false; + } + + // Send Report ID 2 - 1 byte "0x04" + // Enables ZWave packet reports on ID 4 (tx) and ID 5 (rx) + uint8 data = 0x04; + SendFeatureReport(&data, 1, 2); + + return true; + } + catch (Platform::Exception^ ex) + { + return false; + } + }); +} + +//----------------------------------------------------------------------------- +// +// Send data to the HID port +//----------------------------------------------------------------------------- +uint32 HidController::Write +( + uint8* _buffer, + uint32 _length +) +{ + // report Id 0x04 is tx feature report + return SendFeatureReport(_buffer, _length, 0x04); +} + +//----------------------------------------------------------------------------- +// +// Send a feature report with the specified data and report ID +//----------------------------------------------------------------------------- +uint32 HidController::SendFeatureReport +( + uint8* _buffer, + uint32 _length, + unsigned short reportId +) +{ + auto featureReport = m_device->CreateFeatureReport(); + auto dataWriter = ref new DataWriter(); + + auto array = ref new Array(_buffer, _length); + dataWriter->WriteBytes(ArrayReference(_buffer, _length)); + + featureReport->Data = dataWriter->DetachBuffer(); + + uint32 bytesWritten = 0; + try + { + bytesWritten = create_task(m_device->SendFeatureReportAsync(featureReport)).get(); + } + catch (Platform::Exception^) + { + } + return bytesWritten; +} diff --git a/cpp/src/platform/winRT/HidControllerWinRT.h b/cpp/src/platform/winRT/HidControllerWinRT.h new file mode 100644 index 00000000..058d0c37 --- /dev/null +++ b/cpp/src/platform/winRT/HidControllerWinRT.h @@ -0,0 +1,125 @@ +//----------------------------------------------------------------------------- +// +// HidControllerImpl.h +// +// WinRT implementation of a HidController +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- + +#ifndef _HidControllerImpl_H +#define _HidControllerImpl_H + +#include + +#include "Defs.h" +#include "platform/Controller.h" +#include + +namespace OpenZWave +{ + class HidController : public Controller + { + public: + + /** + * Constructor. + * Creates an object that represents a HID port. + */ + HidController(); + + /** + * Destructor. + * Destroys the HID port object. + */ + virtual ~HidController(); + + /** + * Set the USB vendor ID search value. The HID port must be closed for the setting to be accepted. + * @param _baud Vendor ID value to match when enumerating USB HID devices. + * @return True if the vendor ID value was accepted. + * @see Open, Close + */ + bool SetVendorId(uint32 const _vendorId); + + /** + * Set the USB product ID search value. The HID port must be closed for the setting to be accepted. + * @param _parity Product ID value to match when enumerating USB HID devices. + * @return True if the product ID value was accepted. + * @see Open, Close + */ + bool SetProductId(uint32 const _productId); + + /** + * Set the USB serial number search value. The HID port must be closed for the setting to be accepted. + * @param _parity Serial number string to match when enumerating USB HID devices. If empty, any serial number will be accepted. + * @return True if the serial number value was accepted. + * @see Open, Close + */ + bool SetSerialNumber(string const& _serialNumber); + + /** + * Open a HID port. + * Attempts to open a HID port and initialize it with the specified paramters. + * @param _HidControllerName The name of the port to open. For example, ttyS1 on Linux, or \\.\COM2 in Windows. + * @return True if the port was opened and configured successfully. + * @see Close, Read, Write + */ + bool Open(string const& _hidControllerName); + + /** + * Close a HID port. + * Closes the HID port. + * @return True if the port was closed successfully, or false if the port was already closed, or an error occurred. + * @see Open + */ + bool Close(); + + /** + * Write to a HID port. + * Attempts to write data to an open HID port. + * @param _buffer Pointer to a block of memory containing the data to be written. + * @param _length Length in bytes of the data. + * @return The number of bytes written. + * @see Read, Open, Close + */ + uint32 Write(uint8* _buffer, uint32 _length); + + private: + + uint32 SendFeatureReport( uint8* _buffer, uint32 _length, unsigned short reportId ); + Concurrency::task Init(); + + Windows::Devices::HumanInterfaceDevice::HidDevice ^ m_device; + Windows::Foundation::EventRegistrationToken m_inputReportEventToken; + + uint32 m_vendorId; + uint32 m_productId; + string m_serialNumber; + string m_hidControllerName; + bool m_bOpen; + }; + +} // namespace OpenZWave + +#endif //_HidControllerImpl_H + diff --git a/cpp/src/platform/winRT/LogImpl.cpp b/cpp/src/platform/winRT/LogImpl.cpp new file mode 100644 index 00000000..64105d0d --- /dev/null +++ b/cpp/src/platform/winRT/LogImpl.cpp @@ -0,0 +1,350 @@ +//----------------------------------------------------------------------------- +// +// LogImpl.cpp +// +// WinRT implementation of message and error logging +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "LogImpl.h" + +#ifdef MINGW + +#define vsprintf_s vsnprintf + +#define strcpy_s(DEST, NUM, SOURCE) strncpy(DEST, SOURCE, NUM) + +errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) +{ + if (!pFile) + { + _set_errno(EINVAL); + return EINVAL; + } + + *pFile = fopen(filename, mode); + + if (!*pFile) + { + return errno; + } + + return 0; +} + +#endif + + + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +LogImpl::LogImpl +( + string const& _filename, + bool const _bAppendLog, + bool const _bConsoleOutput, + LogLevel const _saveLevel, + LogLevel const _queueLevel, + LogLevel const _dumpTrigger +): + m_filename( _filename ), // name of log file + m_bAppendLog( _bAppendLog ), // true to append (and not overwrite) any existing log + m_bConsoleOutput( _bConsoleOutput ), // true to provide a copy of output to console + m_saveLevel( _saveLevel ), // level of messages to log to file + m_queueLevel( _queueLevel ), // level of messages to log to queue + m_dumpTrigger( _dumpTrigger ) // dump queued messages when this level is seen +{ + string accessType; + + // create an adjusted file name and timestamp string + string timeStr = GetTimeStampString(); + + if ( m_bAppendLog ) + { + accessType = "a"; + } + else + { + accessType = "w"; + } + + FILE* pFile; + if( !fopen_s( &pFile, m_filename.c_str(), accessType.c_str() ) ) + { + fprintf( pFile, "\nLogging started %s\n\n", timeStr.c_str() ); + fclose( pFile ); + } +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +LogImpl::~LogImpl +( +) +{ +} + +//----------------------------------------------------------------------------- +// +// Write to the log +//----------------------------------------------------------------------------- +void LogImpl::Write +( + LogLevel _logLevel, + uint8 const _nodeId, + char const* _format, + va_list _args +) +{ + // create a timestamp string + string timeStr = GetTimeStampString(); + string nodeStr = GetNodeString( _nodeId ); + string logLevelStr = GetLogLevelString(_logLevel); + + // handle this message + if( (_logLevel <= m_queueLevel) || (_logLevel == LogLevel_Internal) ) // we're going to do something with this message... + { + char lineBuf[1024]; + if( !_format || ( _format[0] == 0 ) ) + { + strcpy_s( lineBuf, 1024, "" ); + } + else + { + vsprintf_s( lineBuf, sizeof(lineBuf), _format, _args ); + } + + // should this message be saved to file (and possibly written to console?) + if( (_logLevel <= m_saveLevel) || (_logLevel == LogLevel_Internal) ) + { + // save to file + FILE* pFile = NULL; + if( !fopen_s( &pFile, m_filename.c_str(), "a" ) || m_bConsoleOutput ) + { + if( _logLevel != LogLevel_Internal ) // don't add a second timestamp to display of queued messages + { + if( pFile != NULL ) + { + fprintf( pFile, "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + } + if( m_bConsoleOutput ) + { + printf( "%s%s%s", timeStr.c_str(), logLevelStr.c_str(), nodeStr.c_str() ); + } + } + + // print message to file (and possibly screen) + if( pFile != NULL ) + { + fprintf( pFile, "%s", lineBuf ); + fprintf( pFile, "\n" ); + fclose( pFile ); + } + if( m_bConsoleOutput ) + { + printf( "%s", lineBuf ); + printf( "\n" ); + } + + } + } + + if( _logLevel != LogLevel_Internal ) + { + char queueBuf[1024]; + string threadStr = GetThreadId(); + sprintf_s( queueBuf, sizeof(queueBuf), "%s%s%s", timeStr.c_str(), threadStr.c_str(), lineBuf ); + Queue( queueBuf ); + } + } + + // now check to see if the _dumpTrigger has been hit + if( (_logLevel <= m_dumpTrigger) && (_logLevel != LogLevel_Internal) && (_logLevel != LogLevel_Always) ) + { + QueueDump(); + } +} + +//----------------------------------------------------------------------------- +// +// Write to the log queue +//----------------------------------------------------------------------------- +void LogImpl::Queue +( + char const* _buffer +) +{ + string bufStr = _buffer; + m_logQueue.push_back( bufStr ); + + // rudimentary queue size management + if( m_logQueue.size() > 500 ) + { + m_logQueue.pop_front(); + } +} + +//----------------------------------------------------------------------------- +// +// Dump the LogQueue to output device +//----------------------------------------------------------------------------- +void LogImpl::QueueDump +( +) +{ + Log::Write( LogLevel_Internal, "\n\nDumping queued log messages\n"); + list::iterator it = m_logQueue.begin(); + while( it != m_logQueue.end() ) + { + string strTemp = *it; + Log::Write( LogLevel_Internal, strTemp.c_str() ); + ++it; + } + m_logQueue.clear(); + Log::Write( LogLevel_Internal, "\nEnd of queued log message dump\n\n"); +} + +//----------------------------------------------------------------------------- +// +// Clear the LogQueue +//----------------------------------------------------------------------------- +void LogImpl::QueueClear +( +) +{ + m_logQueue.clear(); +} + +//----------------------------------------------------------------------------- +// +// Sets the various log state variables +//----------------------------------------------------------------------------- +void LogImpl::SetLoggingState +( + LogLevel _saveLevel, + LogLevel _queueLevel, + LogLevel _dumpTrigger +) +{ + m_saveLevel = _saveLevel; + m_queueLevel = _queueLevel; + m_dumpTrigger = _dumpTrigger; +} + +//----------------------------------------------------------------------------- +// +// Generate a string with formatted current time +//----------------------------------------------------------------------------- +string LogImpl::GetTimeStampString +( +) +{ + // Get a timestamp + SYSTEMTIME time; + ::GetLocalTime( &time ); + + // create a time stamp string for the log message + char buf[100]; + sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); + string str = buf; + return str; +} + +//----------------------------------------------------------------------------- +// +// Generate a string with formatted node id +//----------------------------------------------------------------------------- +string LogImpl::GetNodeString +( + uint8 const _nodeId +) +{ + if( _nodeId == 0 ) + { + return ""; + } + else + if( _nodeId == 255 ) // should make distinction between broadcast and controller better for SwitchAll broadcast + { + return "contrlr, "; + } + else + { + char buf[20]; + snprintf( buf, sizeof(buf), "Node%03d, ", _nodeId ); + return buf; + } +} + +//----------------------------------------------------------------------------- +// +// Generate a string with formatted thread id +//----------------------------------------------------------------------------- +string LogImpl::GetThreadId +( +) +{ + char buf[20]; + DWORD dwThread = ::GetCurrentThreadId(); + sprintf_s( buf, sizeof(buf), "%04d ", dwThread ); + string str = buf; + return str; +} + +//----------------------------------------------------------------------------- +// +// Provide a new log file name (applicable to future writes) +//----------------------------------------------------------------------------- +void LogImpl::SetLogFileName +( + const string &_filename +) +{ + m_filename = _filename; +} +//----------------------------------------------------------------------------- +// +// Provide a new log file name (applicable to future writes) +//----------------------------------------------------------------------------- +string LogImpl::GetLogLevelString +( + LogLevel _level +) +{ + if ((_level >= LogLevel_None) && (_level <= LogLevel_Internal)) { + char buf[20]; + snprintf( buf, sizeof(buf), "%s, ", LogLevelString[_level] ); + return buf; + } + else + return "Unknown, "; +} diff --git a/cpp/src/platform/winRT/LogImpl.h b/cpp/src/platform/winRT/LogImpl.h new file mode 100644 index 00000000..729470cf --- /dev/null +++ b/cpp/src/platform/winRT/LogImpl.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +// +// LogImpl.h +// +// WinRT implementation of message and error logging +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _LogImpl_H +#define _LogImpl_H + +#include "Defs.h" +#include +#include "platform/Log.h" +#include "Windows.h" + +namespace OpenZWave +{ + /** \brief Windows-specific implementation of the Log class. + */ + class LogImpl : public i_LogImpl + { + private: + friend class Log; + + LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); + ~LogImpl(); + + void Write( LogLevel _level, uint8 const _nodeId, char const* _format, va_list _args ); + void Queue( char const* _buffer ); + void QueueDump(); + void QueueClear(); + void SetLoggingState( LogLevel _saveLevel, LogLevel _queueLevel, LogLevel _dumpTrigger ); + void SetLogFileName( const string &_filename ); + + string GetTimeStampString(); + string GetNodeString( uint8 const _nodeId ); + string GetThreadId(); + string GetLogLevelString(LogLevel _level); + + string m_filename; /**< filename specified by user (default is ozw_log.txt) */ + bool m_bConsoleOutput; /**< if true, send log output to console as well as to the file */ + bool m_bAppendLog; /**< if true, the log file should be appended to any with the same name */ + list m_logQueue; /**< list of queued log messages */ + LogLevel m_saveLevel; + LogLevel m_queueLevel; + LogLevel m_dumpTrigger; + }; + +} // namespace OpenZWave + +#endif //_LogImpl_H + diff --git a/cpp/src/platform/winRT/MutexImpl.cpp b/cpp/src/platform/winRT/MutexImpl.cpp new file mode 100644 index 00000000..25058db4 --- /dev/null +++ b/cpp/src/platform/winRT/MutexImpl.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// +// MutexImpl.cpp +// +// WinRT implementation of the cross-platform mutex +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "MutexImpl.h" + + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +MutexImpl::MutexImpl +( +): + m_lockCount( 0 ) +{ + InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +MutexImpl::~MutexImpl +( +) +{ + DeleteCriticalSection( &m_criticalSection ); +} + +//----------------------------------------------------------------------------- +// +// Lock the mutex +//----------------------------------------------------------------------------- +bool MutexImpl::Lock +( + bool const _bWait // = true; +) +{ + if( _bWait ) + { + // We will wait for the lock + EnterCriticalSection( &m_criticalSection ); + ++m_lockCount; + return true; + } + + // Returns immediately, even if the lock was not available. + if( TryEnterCriticalSection( &m_criticalSection ) ) + { + ++m_lockCount; + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// +// Release our lock on the mutex +//----------------------------------------------------------------------------- +void MutexImpl::Unlock +( +) +{ + if( !m_lockCount ) + { + // No locks - we have a mismatched lock/release pair + assert(0); + } + else + { + --m_lockCount; + LeaveCriticalSection( &m_criticalSection ); + } +} + +//----------------------------------------------------------------------------- +// +// Test whether the mutex is free +//----------------------------------------------------------------------------- +bool MutexImpl::IsSignalled +( +) +{ + return( 0 == m_lockCount ); +} + diff --git a/cpp/src/platform/winRT/MutexImpl.h b/cpp/src/platform/winRT/MutexImpl.h new file mode 100644 index 00000000..6e4d3b8c --- /dev/null +++ b/cpp/src/platform/winRT/MutexImpl.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// +// MutexImpl.h +// +// WinRT implementation of the cross-platform mutex +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _MutexImpl_H +#define _MutexImpl_H + +#include + + +namespace OpenZWave +{ + /** \brief Windows-specific implementation of the Mutex class. + */ + class MutexImpl + { + private: + friend class Mutex; + + MutexImpl(); + ~MutexImpl(); + + bool Lock( bool const _bWait = true ); + void Unlock(); + + bool IsSignalled(); + + CRITICAL_SECTION m_criticalSection; + uint32 m_lockCount; // Keep track of the locks (there can be more than one if they occur on the same thread. + }; + +} // namespace OpenZWave + +#endif //_MutexIF_H + diff --git a/cpp/src/platform/winRT/SerialControllerImpl.cpp b/cpp/src/platform/winRT/SerialControllerImpl.cpp new file mode 100644 index 00000000..780686e6 --- /dev/null +++ b/cpp/src/platform/winRT/SerialControllerImpl.cpp @@ -0,0 +1,254 @@ +//----------------------------------------------------------------------------- +// +// SerialControllerImpl.cpp +// +// WinRT Implementation of the cross-platform serial port +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "SerialControllerImpl.h" + +#include "platform/Log.h" +#include +#include + +using namespace OpenZWave; +using namespace Windows::Devices::SerialCommunication; +using namespace Windows::Devices::Enumeration; +using namespace Windows::Storage::Streams; +using namespace Windows::Foundation; +using namespace Concurrency; +using namespace Platform; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +SerialControllerImpl::SerialControllerImpl( SerialController* _owner) + : m_owner( _owner ) +{ +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +SerialControllerImpl::~SerialControllerImpl() +{ + Close(); +} + +//----------------------------------------------------------------------------- +// +// Close the serial port +//----------------------------------------------------------------------------- +void SerialControllerImpl::Close() +{ + // cancel read task + m_readTaskCancelationTokenSource.cancel(); +} + +//----------------------------------------------------------------------------- +// +// Open the serial port +//----------------------------------------------------------------------------- +bool SerialControllerImpl::Open() +{ + Log::Write(LogLevel_Info, "Trying to open serial port %s", m_owner->m_serialControllerName.c_str()); + + try + { + auto selector = SerialDevice::GetDeviceSelectorFromUsbVidPid(0x10C4, 0xEA60); + + return create_task(DeviceInformation::FindAllAsync(selector)) + .then([this](DeviceInformationCollection ^ devices) -> IAsyncOperation ^ + { + wstring ourId(m_owner->m_serialControllerName.begin(), m_owner->m_serialControllerName.end()); + for (auto iterator = devices->First(); iterator->HasCurrent; iterator->MoveNext()) + { + wstring currentId = iterator->Current->Id->Data(); + if (currentId.find(ourId) != wstring::npos) + { + return SerialDevice::FromIdAsync(iterator->Current->Id); + } + } + return create_async([]() -> SerialDevice ^ { return nullptr; }); + + }).then([this](SerialDevice ^ device) -> bool + { + if (device == nullptr) + { + return false; + } + m_serialDevice = device; + + m_serialDevice->BaudRate = m_owner->m_baud; + m_serialDevice->DataBits = 8; + switch (m_owner->m_stopBits) + { + case SerialController::StopBits::StopBits_One: + { + m_serialDevice->StopBits = SerialStopBitCount::One; + break; + } + case SerialController::StopBits::StopBits_OneAndAHalf: + { + m_serialDevice->StopBits = SerialStopBitCount::OnePointFive; + break; + } + case SerialController::StopBits::StopBits_Two: + { + m_serialDevice->StopBits = SerialStopBitCount::Two; + break; + } + } + + switch (m_owner->m_parity) + { + case SerialController::Parity::Parity_Even: + { + m_serialDevice->Parity = SerialParity::Even; + break; + } + case SerialController::Parity::Parity_Mark: + { + m_serialDevice->Parity = SerialParity::Mark; + break; + } + case SerialController::Parity::Parity_None: + { + m_serialDevice->Parity = SerialParity::None; + break; + } + case SerialController::Parity::Parity_Odd: + { + m_serialDevice->Parity = SerialParity::Odd; + break; + } + case SerialController::Parity::Parity_Space: + { + m_serialDevice->Parity = SerialParity::Space; + break; + } + } + + Windows::Foundation::TimeSpan timespan; + timespan.Duration = 1; + m_serialDevice->ReadTimeout = timespan; + + StartReadTask(); + + return true; + }).get(); + } + catch (...) + { + return false; + } +} + +//----------------------------------------------------------------------------- +// +// Start a background task which reads available data and passes it along to SerialController +//----------------------------------------------------------------------------- +void SerialControllerImpl::StartReadTask() +{ + // Read serial data on background task + cancellation_token token = m_readTaskCancelationTokenSource.get_token(); + + create_task([token, this]() + { + uint32 readBufferLength = 512; + Buffer ^ buffer = ref new Buffer(readBufferLength); + + for (;;) + { + try + { + create_task(m_serialDevice->InputStream->ReadAsync(buffer, readBufferLength, InputStreamOptions::None)) + .then([&, this](IBuffer ^ outBuffer) + { + auto reader = DataReader::FromBuffer(outBuffer); + auto bytesRead = reader->UnconsumedBufferLength; + + std::vector byteVector(bytesRead); + if (!byteVector.empty()) + { + reader->ReadBytes(::Platform::ArrayReference(byteVector.data(), bytesRead)); + m_owner->Put(byteVector.data(), bytesRead); + } + }).wait(); + } + catch (Platform::Exception^ ex) + { + if (ex->HResult == HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)) + { + m_owner->Close(); + } + } + + if (token.is_canceled()) + { + cancel_current_task(); + } + } + }, token); +} + +//----------------------------------------------------------------------------- +// +// Send data to the serial port +//----------------------------------------------------------------------------- +uint32 SerialControllerImpl::Write +( + uint8* _buffer, + uint32 _length +) +{ + uint32 retVal = 0; + + if (m_serialDevice == nullptr) + { + //Error + Log::Write(LogLevel_Error, "ERROR: Serial port must be opened before writing\n"); + return 0; + } + + DataWriter ^ writer = ref new DataWriter(); + writer->WriteBytes(ref new Platform::Array(_buffer, _length)); + try + { + auto writeTask = create_task(m_serialDevice->OutputStream->WriteAsync(writer->DetachBuffer())); + + // since the consumer of this function expects this to be synchronous, just wait here. + retVal = writeTask.get(); + } + catch (Platform::Exception^ ) + { + //ignore - return 0 + retVal = 0; + } + + return retVal; +} diff --git a/cpp/src/platform/winRT/SerialControllerImpl.h b/cpp/src/platform/winRT/SerialControllerImpl.h new file mode 100644 index 00000000..0434e43d --- /dev/null +++ b/cpp/src/platform/winRT/SerialControllerImpl.h @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// +// SerialControllerImpl.h +// +// WinRT Implementation of the cross-platform serial port +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- + +#ifndef _SerialControllerImpl_H +#define _SerialControllerImpl_H + +#include +#include + +#include "Defs.h" +#include "platform/SerialController.h" + +namespace OpenZWave +{ + class SerialControllerImpl + { + private: + friend class SerialController; + + SerialControllerImpl( SerialController* _owner ); + ~SerialControllerImpl(); + + bool Open(); + void Close(); + + uint32 Write( uint8* _buffer, uint32 _length ); + void StartReadTask(); + + Windows::Devices::SerialCommunication::SerialDevice ^ m_serialDevice; + Concurrency::cancellation_token_source m_readTaskCancelationTokenSource; + + SerialController* m_owner; + }; + +} // namespace OpenZWave + +#endif //_SerialControllerImpl_H + diff --git a/cpp/src/platform/winRT/ThreadImpl.cpp b/cpp/src/platform/winRT/ThreadImpl.cpp new file mode 100644 index 00000000..4c3c15ef --- /dev/null +++ b/cpp/src/platform/winRT/ThreadImpl.cpp @@ -0,0 +1,148 @@ +//----------------------------------------------------------------------------- +// +// ThreadImpl.cpp +// +// WinRT implementation of a cross-platform thread +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Event.h" +#include "platform/Thread.h" +#include "ThreadImpl.h" +#include "Options.h" + +using namespace OpenZWave; +using namespace Concurrency; +using namespace Windows::Foundation; +using namespace Windows::System::Threading; + +int32 ThreadImpl::s_threadTerminateTimeout = -1; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +ThreadImpl::ThreadImpl +( + Thread* _owner, + string const& _name +): + m_owner( _owner ), + m_bIsRunning( false ), + m_name( _name ) +{ + static bool staticsInitialized = false; + if (!staticsInitialized) + { + if (Options::Get() != nullptr) + { + Options::Get()->GetOptionAsInt("ThreadTerminateTimeout", &s_threadTerminateTimeout); + } + staticsInitialized = true; + } +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +ThreadImpl::~ThreadImpl () +{ +} + +//----------------------------------------------------------------------------- +// +// Start a function running on this thread +//----------------------------------------------------------------------------- +bool ThreadImpl::Start +( + Thread::pfnThreadProc_t _pfnThreadProc, + Event* _exitEvent, + void* _context +) +{ + // Create a thread to run the specified function + m_pfnThreadProc = _pfnThreadProc; + m_context = _context; + m_exitEvent = _exitEvent; + m_exitEvent->Reset(); + + create_task([this]() + { + m_bIsRunning = true; + try + { + m_pfnThreadProc(m_exitEvent, m_context); + } + catch (Platform::Exception^) + { + } + + m_bIsRunning = false; + // Let any watchers know that the thread has finished running. + m_owner->Notify(); + }); + return true; +} + +//----------------------------------------------------------------------------- +// +// Cause thread to sleep for the specified number of milliseconds +//----------------------------------------------------------------------------- +void ThreadImpl::Sleep +( + uint32 _millisecs +) +{ + ::Sleep(_millisecs); +} + +//----------------------------------------------------------------------------- +// +// Force the thread to stop +//----------------------------------------------------------------------------- +bool ThreadImpl::Terminate +( +) +{ + // No way to do this on WinRT, so give the thread a bit of extra time to exit on its own + if( !m_bIsRunning ) + { + return false; + } + + if (Wait::Single(m_owner, s_threadTerminateTimeout) < 0) + { + return false; + } + return true; +} + +//----------------------------------------------------------------------------- +// +// Test whether the thread has completed +//----------------------------------------------------------------------------- +bool ThreadImpl::IsSignalled() +{ + return !m_bIsRunning; +} \ No newline at end of file diff --git a/cpp/src/platform/winRT/ThreadImpl.h b/cpp/src/platform/winRT/ThreadImpl.h new file mode 100644 index 00000000..3dec48cc --- /dev/null +++ b/cpp/src/platform/winRT/ThreadImpl.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// +// ThreadImpl.h +// +// WinRT implementation of a cross-platform thread +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _ThreadImpl_H +#define _ThreadImpl_H + +#include +#include +#include "platform/Thread.h" +#include + +namespace OpenZWave +{ + class Thread; + class Event; + + /** \brief Windows-specific implementation of the Thread class. + */ + class ThreadImpl + { + private: + friend class Thread; + + ThreadImpl( Thread* _owner, string const& _name ); + ~ThreadImpl(); + + bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); + void Sleep( uint32 _milliseconds ); + bool Terminate(); + + bool IsSignalled(); + + void Run(); + static DWORD WINAPI ThreadProc( void* _pArg ); + + Thread* m_owner; + Event* m_exitEvent; + Thread::pfnThreadProc_t m_pfnThreadProc; + void* m_context; + bool m_bIsRunning; + string m_name; + + static int32 s_threadTerminateTimeout; + }; + +} // namespace OpenZWave + +#endif //_ThreadImpl_H + diff --git a/cpp/src/platform/winRT/TimeStampImpl.cpp b/cpp/src/platform/winRT/TimeStampImpl.cpp new file mode 100644 index 00000000..bd63c8f0 --- /dev/null +++ b/cpp/src/platform/winRT/TimeStampImpl.cpp @@ -0,0 +1,114 @@ +//----------------------------------------------------------------------------- +// +// TimeStampImpl.cpp +// +// WinRT implementation of a TimeStamp +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "TimeStampImpl.h" + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +TimeStampImpl::TimeStampImpl +( +) +{ + SetTime(0); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +TimeStampImpl::~TimeStampImpl +( +) +{ +} + +//----------------------------------------------------------------------------- +// +// Sets the timestamp to now, plus an offset in milliseconds +//----------------------------------------------------------------------------- +void TimeStampImpl::SetTime +( + int32 _milliseconds // = 0 +) +{ + int64 offset = ((int64)_milliseconds) * 10000LL; // Timestamp is stored in 100ns steps. + + GetSystemTimeAsFileTime( (FILETIME*)&m_stamp ); + m_stamp += offset; +} + +//----------------------------------------------------------------------------- +// +// Gets the difference between now and the timestamp time in milliseconds +//----------------------------------------------------------------------------- +int32 TimeStampImpl::TimeRemaining +( +) +{ + int64 now; + GetSystemTimeAsFileTime( (FILETIME*)&now ); + + return (int32)( ( m_stamp - now ) / 10000LL ); +} + +//----------------------------------------------------------------------------- +// +// Return a string representation +//----------------------------------------------------------------------------- +string TimeStampImpl::GetAsString +( +) +{ + // Convert m_stamp (FILETIME) to SYSTEMTIME for ease of use + SYSTEMTIME time; + ::FileTimeToSystemTime( (FILETIME*)&m_stamp, &time ); + + char buf[100]; + sprintf_s( buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d:%03d ", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); + string str = buf; + return str; +} + +//----------------------------------------------------------------------------- +// +// Overload the subtract operator to get the difference between two +// timestamps in milliseconds +//----------------------------------------------------------------------------- +int32 TimeStampImpl::operator- +( + TimeStampImpl const& _other +) +{ + return (int32)( ( m_stamp - _other.m_stamp ) / 10000LL ); +} diff --git a/cpp/src/platform/winRT/TimeStampImpl.h b/cpp/src/platform/winRT/TimeStampImpl.h new file mode 100644 index 00000000..0ed042a3 --- /dev/null +++ b/cpp/src/platform/winRT/TimeStampImpl.h @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------- +// +// TimeStampImpl.h +// +// WinRT implementation of a TimeStamp +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _TimeStampImpl_H +#define _TimeStampImpl_H + +#include "Defs.h" + +namespace OpenZWave +{ + /** \brief Windows implementation of a timestamp. + */ + class TimeStampImpl + { + public: + /** + * Constructor. + * Creates a TimeStampImpl object. + */ + TimeStampImpl(); + + /** + * Destructor. + * Destroys the TimeStampImpl object. + */ + ~TimeStampImpl(); + + /** + * SetTime. Sets the timestamp to now, plus the offset in milliseconds. + * \param _milliseconds positive or negative offset from + * now in milliseconds. + */ + void SetTime( int32 _milliseconds ); + + /** + * TimeRemaining. Gets the difference between now and the timestamp + * time in milliseconds. + * \return milliseconds remaining until we reach the timestamp. The + * return value is negative if the timestamp is in the past. + */ + int32 TimeRemaining(); + + /** + * Return as as string + */ + string GetAsString(); + + /** + * Overload the subtract operator to get the difference between + * two timestamps in milliseconds. + */ + int32 operator- ( TimeStampImpl const& _other ); + + private: + TimeStampImpl( TimeStampImpl const& ); // prevent copy + TimeStampImpl& operator = ( TimeStampImpl const& ); // prevent assignment + + int64 m_stamp; + }; + +} // namespace OpenZWave + +#endif //_TimeStampImpl_H + diff --git a/cpp/src/platform/winRT/WaitImpl.cpp b/cpp/src/platform/winRT/WaitImpl.cpp new file mode 100644 index 00000000..f9c82774 --- /dev/null +++ b/cpp/src/platform/winRT/WaitImpl.cpp @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// +// WaitImpl.cpp +// +// WinRT implementation of a base class for objects we +// want to be able to wait for. +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 "Defs.h" +#include "platform/Wait.h" +#include "WaitImpl.h" +#include "platform/Log.h" + +using namespace OpenZWave; + +//----------------------------------------------------------------------------- +// +// Constructor +//----------------------------------------------------------------------------- +WaitImpl::WaitImpl +( + Wait* _owner +): + m_owner( _owner ) +{ + InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); +} + +//----------------------------------------------------------------------------- +// +// Destructor +//----------------------------------------------------------------------------- +WaitImpl::~WaitImpl +( +) +{ + DeleteCriticalSection( &m_criticalSection ); +} + +//----------------------------------------------------------------------------- +// +// Add a watcher to our object. +//----------------------------------------------------------------------------- +void WaitImpl::AddWatcher +( + Wait::pfnWaitNotification_t _callback, + void* _context +) +{ + // Add the watcher to our list + Watcher watcher; + watcher.m_callback = _callback; + watcher.m_context = _context; + + EnterCriticalSection( &m_criticalSection ); + + m_watchers.push_back( watcher ); + + LeaveCriticalSection( &m_criticalSection ); + + // If the object is already in a signalled state, notify the watcher immediately + if( m_owner->IsSignalled() ) + { + _callback( _context ); + } + +} + +//----------------------------------------------------------------------------- +// +// Remove a watcher from our object. +//----------------------------------------------------------------------------- +bool WaitImpl::RemoveWatcher +( + Wait::pfnWaitNotification_t _callback, + void* _context +) +{ + bool res = false; + EnterCriticalSection( &m_criticalSection ); + + for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) + { + Watcher const& watcher = *it; + if( ( watcher.m_callback == _callback ) && ( watcher.m_context == _context ) ) + { + m_watchers.erase( it ); + res = true; + break; + } + } + + LeaveCriticalSection( &m_criticalSection ); + return res; +} + +//----------------------------------------------------------------------------- +// +// Notify all the watchers that the object has become signalled +//----------------------------------------------------------------------------- +void WaitImpl::Notify +( +) +{ + EnterCriticalSection( &m_criticalSection ); + + for( list::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it ) + { + Watcher const& watcher = *it; + watcher.m_callback( watcher.m_context ); + } + + LeaveCriticalSection( &m_criticalSection ); +} diff --git a/cpp/src/platform/winRT/WaitImpl.h b/cpp/src/platform/winRT/WaitImpl.h new file mode 100644 index 00000000..c1d5be5e --- /dev/null +++ b/cpp/src/platform/winRT/WaitImpl.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// +// WaitImpl.h +// +// WinRT implementation of a base class for objects we +// want to be able to wait for. +// +// Copyright (c) 2015 Microsoft Corporation +// All rights reserved. +// +// 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 . +// +//----------------------------------------------------------------------------- +#ifndef _WaitImpl_H +#define _WaitImpl_H + +#include +#include +#include "Defs.h" +#include "platform/Ref.h" +#include "platform/Wait.h" + +namespace OpenZWave +{ + /** \brief Windows specific implementation of Wait objects. + */ + class WaitImpl + { + private: + friend class Wait; + + WaitImpl( Wait* _owner ); + virtual ~WaitImpl(); + + void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); + bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); + void Notify(); + + static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); + + WaitImpl( Wait const& ); // prevent copy + WaitImpl& operator = ( WaitImpl const& ); // prevent assignment + + struct Watcher + { + Wait::pfnWaitNotification_t m_callback; + void* m_context; + }; + + list m_watchers; + Wait* m_owner; + CRITICAL_SECTION m_criticalSection; + }; + +} // namespace OpenZWave + +#endif //_WaitImpl_H +