update esppilight lib

content of the library is not filtered on 433mhz only
This commit is contained in:
Florian committed 2018-11-28 20:41:37 +01:00
1 parent a275e48ee1
commit 67dd7ac078
1030 files changed
+203335 -116

No files matched your search

@@ -0,0 +1,6 @@
project(openzwave_platform_windows)
file(GLOB ${PROJECT_NAME}_sources "${PROJECT_SOURCE_DIR}/*.cpp")
file(GLOB ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/*.h")
set(${PROJECT_NAME}_files ${${PROJECT_NAME}_sources} ${${PROJECT_NAME}_headers} CACHE INTERNAL "")
@@ -0,0 +1,102 @@
//-----------------------------------------------------------------------------
//
// EventImpl.cpp
//
// Windows implementation of a cross-platform event
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include "../../Defs.h"
#include "EventImpl.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <EventImpl::EventImpl>
// Constructor
//-----------------------------------------------------------------------------
EventImpl::EventImpl
(
)
{
// Create a manual reset event
m_hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
}
//-----------------------------------------------------------------------------
// <EventImpl::~EventImpl>
// Destructor
//-----------------------------------------------------------------------------
EventImpl::~EventImpl
(
)
{
::CloseHandle( m_hEvent );
}
//-----------------------------------------------------------------------------
// <EventImpl::Set>
// Set the event to signalled
//-----------------------------------------------------------------------------
void EventImpl::Set
(
)
{
::SetEvent( m_hEvent );
}
//-----------------------------------------------------------------------------
// <EventImpl::Reset>
// Set the event to not signalled
//-----------------------------------------------------------------------------
void EventImpl::Reset
(
)
{
::ResetEvent( m_hEvent );
}
//-----------------------------------------------------------------------------
// <EventImpl::IsSignalled>
// Test whether the event is set
//-----------------------------------------------------------------------------
bool EventImpl::IsSignalled
(
)
{
return( WAIT_OBJECT_0 == WaitForSingleObject( m_hEvent, 0 ) );
}
//-----------------------------------------------------------------------------
// <EventImpl::Wait>
// Wait for the event to become signalled
//-----------------------------------------------------------------------------
bool EventImpl::Wait
(
int32 const _timeout
)
{
return( WAIT_TIMEOUT != ::WaitForSingleObject( m_hEvent, (DWORD)_timeout ) );
}
@@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
//
// EventImpl.h
//
// Windows implementation of a cross-platform event
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _EventImpl_H
#define _EventImpl_H
#include <windows.h>
#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
@@ -0,0 +1,69 @@
//-----------------------------------------------------------------------------
//
// FileOpsImpl.cpp
//
// Unix implementation of file operations
//
// Copyright (c) 2012, Greg Satz <satz@iranger.com>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include "FileOpsImpl.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <FileOpsImpl::FileOpsImpl>
// Constructor
//-----------------------------------------------------------------------------
FileOpsImpl::FileOpsImpl
(
)
{
}
//-----------------------------------------------------------------------------
// <FileOpsImpl::~FileOpsImpl>
// Destructor
//-----------------------------------------------------------------------------
FileOpsImpl::~FileOpsImpl
(
)
{
}
//-----------------------------------------------------------------------------
// <FileOpsImpl::FolderExists>
// Determine if a folder exists
//-----------------------------------------------------------------------------
bool FileOpsImpl::FolderExists(
const string &_folderName
)
{
int32 ftype = GetFileAttributesA(_folderName.c_str());
if( ftype == INVALID_FILE_ATTRIBUTES )
return false; // something is wrong with _foldername path
if( ftype & FILE_ATTRIBUTE_DIRECTORY )
return true;
return false;
}
@@ -0,0 +1,52 @@
//-----------------------------------------------------------------------------
//
// FileOpsImpl.h
//
// Unix implementation of file operations
//
// Copyright (c) 2012, Greg Satz <satz@iranger.com>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _FileOpsImpl_H
#define _FileOpsImpl_H
#include <stdarg.h>
#include <string>
#include "../../Defs.h"
#include "../FileOps.h"
namespace OpenZWave
{
class FileOpsImpl
{
friend class FileOps;
private:
FileOpsImpl();
~FileOpsImpl();
bool FolderExists( const string &_filename );
};
} // namespace OpenZWave
#endif //_FileOpsImpl_H
@@ -0,0 +1,362 @@
//-----------------------------------------------------------------------------
//
// LogImpl.cpp
//
// Windows implementation of message and error logging
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <list>
#include <sys/time.h>
#include <time.h>
#include "../../Defs.h"
#include "LogImpl.h"
#ifdef _WIN32
#define vsprintf_s vsnprintf
#define sprintf_s snprintf
#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;
//-----------------------------------------------------------------------------
// <LogImpl::LogImpl>
// 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, _filename.c_str(), accessType.c_str() ) )
{
fprintf( pFile, "\nLogging started %s\n\n", timeStr.c_str() );
fclose( pFile );
}
}
//-----------------------------------------------------------------------------
// <LogImpl::~LogImpl>
// Destructor
//-----------------------------------------------------------------------------
LogImpl::~LogImpl
(
)
{
}
//-----------------------------------------------------------------------------
// <LogImpl::Write>
// 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();
}
}
//-----------------------------------------------------------------------------
// <LogImpl::Queue>
// 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();
}
}
//-----------------------------------------------------------------------------
// <LogImpl::QueueDump>
// Dump the LogQueue to output device
//-----------------------------------------------------------------------------
void LogImpl::QueueDump
(
)
{
Log::Write( LogLevel_Internal, "\n\nDumping queued log messages\n");
list<string>::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");
}
//-----------------------------------------------------------------------------
// <LogImpl::Clear>
// Clear the LogQueue
//-----------------------------------------------------------------------------
void LogImpl::QueueClear
(
)
{
m_logQueue.clear();
}
//-----------------------------------------------------------------------------
// <LogImpl::SetLoggingState>
// Sets the various log state variables
//-----------------------------------------------------------------------------
void LogImpl::SetLoggingState
(
LogLevel _saveLevel,
LogLevel _queueLevel,
LogLevel _dumpTrigger
)
{
m_saveLevel = _saveLevel;
m_queueLevel = _queueLevel;
m_dumpTrigger = _dumpTrigger;
}
//-----------------------------------------------------------------------------
// <LogImpl::GetTimeStampAndThreadId>
// Generate a string with formatted current time
//-----------------------------------------------------------------------------
string LogImpl::GetTimeStampString
(
)
{
struct timeval tv;
struct tm tm;
char fmt[64], buf[64], line[256];
gettimeofday(&tv, NULL);
#ifdef _WIN32
struct tm *tm1;
if((tm1 = gmtime(&tv.tv_sec)) != 0) {
memcpy(&tm, tm1, sizeof(struct tm));
#else
if((gmtime_r(&tv.tv_sec, &tm)) != 0) {
#endif
strftime(fmt, sizeof(fmt), "%b %d %H:%M:%S", &tm);
snprintf(buf, sizeof(buf), "%s:%03u", fmt, (unsigned int)tv.tv_usec);
}
sprintf(line, "[%22.22s] %s: [Z-Wave]: ", buf, "pilight-daemon");
string str = line;
return str;
}
//-----------------------------------------------------------------------------
// <LogImpl::GetNodeString>
// 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;
}
}
//-----------------------------------------------------------------------------
// <LogImpl::GetThreadId>
// 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;
}
//-----------------------------------------------------------------------------
// <LogImpl::SetLogFileName>
// Provide a new log file name (applicable to future writes)
//-----------------------------------------------------------------------------
void LogImpl::SetLogFileName
(
const string &_filename
)
{
m_filename = _filename;
}
//-----------------------------------------------------------------------------
// <LogImpl::GetLogLevelString>
// 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, ";
}
@@ -0,0 +1,72 @@
//-----------------------------------------------------------------------------
//
// LogImpl.h
//
// Windows implementation of message and error logging
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _LogImpl_H
#define _LogImpl_H
#include "../../Defs.h"
#include <string>
#include "../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<string> m_logQueue; /**< list of queued log messages */
LogLevel m_saveLevel;
LogLevel m_queueLevel;
LogLevel m_dumpTrigger;
};
} // namespace OpenZWave
#endif //_LogImpl_H
@@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
//
// MutexImpl.cpp
//
// Windows Implementation of the cross-platform mutex
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include "../../Defs.h"
#include "MutexImpl.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <MutexImpl::MutexImpl>
// Constructor
//-----------------------------------------------------------------------------
MutexImpl::MutexImpl
(
):
m_lockCount( 0 )
{
InitializeCriticalSection( &m_criticalSection );
}
//-----------------------------------------------------------------------------
// <MutexImpl::~MutexImpl>
// Destructor
//-----------------------------------------------------------------------------
MutexImpl::~MutexImpl
(
)
{
DeleteCriticalSection( &m_criticalSection );
}
//-----------------------------------------------------------------------------
// <MutexImpl::Lock>
// 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;
}
//-----------------------------------------------------------------------------
// <MutexImpl::Unlock>
// 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 );
}
}
//-----------------------------------------------------------------------------
// <MutexImpl::IsSignalled>
// Test whether the mutex is free
//-----------------------------------------------------------------------------
bool MutexImpl::IsSignalled
(
)
{
return( 0 == m_lockCount );
}
@@ -0,0 +1,58 @@
//-----------------------------------------------------------------------------
//
// MutexImpl.h
//
// Windows Implementation of the cross-platform mutex
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _MutexImpl_H
#define _MutexImpl_H
#include <windows.h>
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
@@ -0,0 +1,410 @@
//-----------------------------------------------------------------------------
//
// SerialControllerImpl.cpp
//
// Windows Implementation of the cross-platform serial port
//
// Copyright (c) 2010 Jason Frazier <frazierjason@gmail.com>
//
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include "../../Defs.h"
#include "SerialControllerImpl.h"
#include "../Log.h"
using namespace OpenZWave;
DWORD WINAPI SerialReadThreadEntryPoint( void* _context );
//-----------------------------------------------------------------------------
// <SerialControllerImpl::SerialControllerImpl>
// Constructor
//-----------------------------------------------------------------------------
SerialControllerImpl::SerialControllerImpl
(
SerialController* _owner
):
m_owner( _owner )
{
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::~SerialControllerImpl>
// Destructor
//-----------------------------------------------------------------------------
SerialControllerImpl::~SerialControllerImpl
(
)
{
CloseHandle( m_hSerialController );
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::Open>
// Open the serial port
//-----------------------------------------------------------------------------
bool SerialControllerImpl::Open
(
)
{
// Try to init the serial port
if( !Init( 1 ) )
{
// Failed. We bail to allow the app a chance to take over, rather than retry
// automatically. Automatic retries only occur after a successful init.
return false;
}
// Create an event to trigger exiting the read thread
m_hExit = ::CreateEvent( NULL, TRUE, FALSE, NULL );
// Start the read thread
m_hThread = ::CreateThread( NULL, 0, SerialReadThreadEntryPoint, this, CREATE_SUSPENDED, NULL );
::ResumeThread( m_hThread );
return true;
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::Close>
// Close the serial port
//-----------------------------------------------------------------------------
void SerialControllerImpl::Close
(
)
{
::SetEvent( m_hExit );
::WaitForSingleObject( m_hThread, INFINITE );
CloseHandle( m_hThread );
m_hThread = INVALID_HANDLE_VALUE;
CloseHandle( m_hExit );
m_hExit = INVALID_HANDLE_VALUE;
CloseHandle( m_hSerialController );
m_hSerialController = INVALID_HANDLE_VALUE;
}
//-----------------------------------------------------------------------------
// <SerialReadThreadEntryPoint>
// Entry point of the thread for receiving data from the serial port
//-----------------------------------------------------------------------------
DWORD WINAPI SerialReadThreadEntryPoint
(
void* _context
)
{
SerialControllerImpl* impl = (SerialControllerImpl*)_context;
if( impl )
{
impl->ReadThreadProc();
}
return 0;
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::ReadThreadProc>
// Handle receiving data
//-----------------------------------------------------------------------------
void SerialControllerImpl::ReadThreadProc
(
)
{
uint32 attempts = 0;
while( true )
{
// Init must have been called successfully during Open, so we
// don't do it again until the end of the loop
if( INVALID_HANDLE_VALUE != m_hSerialController )
{
// Enter read loop. Call will only return if
// an exit is requested or an error occurs
Read();
// Reset the attempts, so we get a rapid retry for temporary errors
attempts = 0;
}
if( attempts < 25 )
{
// Retry every 5 seconds for the first two minutes...
if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hExit, 5000 ) )
{
// Exit signalled.
break;
}
}
else
{
// ...retry every 30 seconds after that
if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hExit, 30000 ) )
{
// Exit signalled.
break;
}
}
Init( ++attempts );
}
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::Init>
// Initialize the serial port
//-----------------------------------------------------------------------------
bool SerialControllerImpl::Init
(
uint32 const _attempts
)
{
Log::Write( LogLevel_Info, " Trying to open serial port %s (Attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts );
m_hSerialController = CreateFileA( m_owner->m_serialControllerName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL );
if( INVALID_HANDLE_VALUE == m_hSerialController )
{
//Error
Log::Write( LogLevel_Error, "ERROR: Cannot open serial port %s. Error code %d\n", m_owner->m_serialControllerName.c_str(), GetLastError() );
goto SerialOpenFailure;
}
// Configure the serial device parameters
// Build on the current configuration
DCB dcb;
if( !GetCommState( m_hSerialController, &dcb ) )
{
//Error. Clean up and exit
Log::Write( LogLevel_Error, "ERROR: Failed to read serial port state" );
goto SerialOpenFailure;
}
// Fill in the Device Control Block
dcb.BaudRate = (DWORD)m_owner->m_baud;
dcb.ByteSize = 8;
dcb.Parity = (BYTE)m_owner->m_parity;
dcb.StopBits = (BYTE)m_owner->m_stopBits;
if( !SetCommState( m_hSerialController, &dcb) )
{
//Error. Clean up and exit
Log::Write( LogLevel_Error, "ERROR: Failed to set serial port state" );
goto SerialOpenFailure;
}
// Set the timeouts for the serial port
COMMTIMEOUTS commTimeouts;
commTimeouts.ReadIntervalTimeout = MAXDWORD;
commTimeouts.ReadTotalTimeoutConstant = 0;
commTimeouts.ReadTotalTimeoutMultiplier = 0;
commTimeouts.WriteTotalTimeoutConstant = 0;
commTimeouts.WriteTotalTimeoutMultiplier = 0;
if( !SetCommTimeouts( m_hSerialController, &commTimeouts ) )
{
// Error. Clean up and exit
Log::Write( LogLevel_Error, "ERROR: Failed to set serial port timeouts" );
goto SerialOpenFailure;
}
// Set the serial port to signal when data is received
if( !SetCommMask( m_hSerialController, EV_RXCHAR ) )
{
//Error. Clean up and exit
Log::Write( LogLevel_Info, "ERROR: Failed to set serial port mask" );
goto SerialOpenFailure;
}
// Clear any residual data from the serial port
PurgeComm( m_hSerialController, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR );
// Open successful
Log::Write( LogLevel_Info, " Serial port %s opened (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts );
return true;
SerialOpenFailure:
Log::Write( LogLevel_Info, "ERROR: Failed to open serial port %s (attempt %d)", m_owner->m_serialControllerName.c_str(), _attempts );
CloseHandle( m_hSerialController );
m_hSerialController = INVALID_HANDLE_VALUE;
return false;
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::Read>
// Read data from the serial port
//-----------------------------------------------------------------------------
void SerialControllerImpl::Read
(
)
{
uint8 buffer[256];
OVERLAPPED overlapped;
memset( &overlapped, 0, sizeof(overlapped) );
overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
while( true )
{
// Try to read all available data from the serial port
DWORD bytesRead = 0;
do
{
if( ::ReadFile( m_hSerialController, buffer, 256, NULL, &overlapped ) )
{
// Read completed
GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE );
// Copy to the stream buffer
if( bytesRead > 0 )
m_owner->Put( buffer, bytesRead );
}
else
{
//Wait for the read to complete
if( ERROR_IO_PENDING == GetLastError() )
{
// Wait for the read to complete or the
// signal that this thread should exit.
HANDLE handles[2];
handles[0] = overlapped.hEvent;
handles[1] = m_hExit;
DWORD res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE );
if( (WAIT_OBJECT_0+1) == res )
{
// Exit signalled. Cancel the read.
goto exitRead;
}
if( WAIT_TIMEOUT == res )
{
// Timed out - should never happen
goto exitRead;
}
// Read completed
GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE );
// Copy to the stream buffer
if( bytesRead > 0 )
m_owner->Put( buffer, bytesRead );
}
else
{
// An error has occurred
goto exitRead;
}
}
}
while( bytesRead > 0 );
// Clear the event
ResetEvent( overlapped.hEvent );
// Nothing available to read, so wait for the next rx char event
DWORD dwEvtMask;
if( !WaitCommEvent( m_hSerialController, &dwEvtMask, &overlapped ) )
{
if( ERROR_IO_PENDING == GetLastError() )
{
// Wait for either some data to arrive or
// the signal that this thread should exit.
HANDLE handles[2];
handles[0] = overlapped.hEvent;
handles[1] = m_hExit;
DWORD res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE );
if( (WAIT_OBJECT_0+1) == res )
{
// Exit signalled. Prevent WaitCommEvent from corrupting the
// stack by forcing it to exit.
goto exitRead;
}
if( WAIT_TIMEOUT == res )
{
// Timed out - should never happen
goto exitRead;
}
GetOverlappedResult( m_hSerialController, &overlapped, &bytesRead, TRUE );
}
}
// Clear the event
ResetEvent( overlapped.hEvent );
// Loop back to the top to read the waiting data
}
exitRead:
// Exit event has been signalled, or an error has occurred
SetCommMask( m_hSerialController, 0 );
CancelIo( m_hSerialController );
CloseHandle( overlapped.hEvent );
}
//-----------------------------------------------------------------------------
// <SerialControllerImpl::Write>
// Send data to the serial port
//-----------------------------------------------------------------------------
uint32 SerialControllerImpl::Write
(
uint8* _buffer,
uint32 _length
)
{
if( INVALID_HANDLE_VALUE == m_hSerialController )
{
//Error
Log::Write( LogLevel_Error, "ERROR: Serial port must be opened before writing\n" );
return 0;
}
// Write the data
OVERLAPPED overlapped;
memset( &overlapped, 0, sizeof(overlapped) );
overlapped.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
DWORD bytesWritten;
if( !::WriteFile( m_hSerialController, _buffer, _length, &bytesWritten, &overlapped ) )
{
//Wait for the write to complete
if( ERROR_IO_PENDING == GetLastError() )
{
GetOverlappedResult( m_hSerialController, &overlapped, &bytesWritten, TRUE );
}
else
{
Log::Write( LogLevel_Error, "ERROR: Serial port write (0x%.8x)", GetLastError() );
}
}
CloseHandle( overlapped.hEvent );
return (uint32)bytesWritten;
}
@@ -0,0 +1,66 @@
//-----------------------------------------------------------------------------
//
// SerialControllerImpl.h
//
// Windows Implementation of the cross-platform serial port
//
// Copyright (c) 2010 Jason Frazier <frazierjason@gmail.com>
//
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _SerialControllerImpl_H
#define _SerialControllerImpl_H
#include <windows.h>
#include "../../Defs.h"
#include "../SerialController.h"
namespace OpenZWave
{
class SerialControllerImpl
{
public:
void ReadThreadProc();
private:
friend class SerialController;
SerialControllerImpl( SerialController* _owner );
~SerialControllerImpl();
bool Open();
void Close();
uint32 Write( uint8* _buffer, uint32 _length );
bool Init( uint32 const _attempts );
void Read();
SerialController* m_owner;
HANDLE m_hThread;
HANDLE m_hExit;
HANDLE m_hSerialController;
};
} // namespace OpenZWave
#endif //_SerialControllerImpl_H
@@ -0,0 +1,158 @@
//-----------------------------------------------------------------------------
//
// ThreadImpl.cpp
//
// Windows implementation of a cross-platform thread
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include "../../Defs.h"
#include "../Event.h"
#include "../Thread.h"
#include "ThreadImpl.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <ThreadImpl::ThreadImpl>
// Constructor
//-----------------------------------------------------------------------------
ThreadImpl::ThreadImpl
(
Thread* _owner,
string const& _name
):
m_owner( _owner ),
m_hThread( INVALID_HANDLE_VALUE ),
m_bIsRunning( false ),
m_name( _name )
{
}
//-----------------------------------------------------------------------------
// <ThreadImpl::~ThreadImpl>
// Destructor
//-----------------------------------------------------------------------------
ThreadImpl::~ThreadImpl
(
)
{
}
//-----------------------------------------------------------------------------
// <ThreadImpl::Start>
// 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();
HANDLE hThread = ::CreateThread( NULL, 0, ThreadImpl::ThreadProc, this, CREATE_SUSPENDED, NULL );
m_hThread = hThread;
::ResumeThread( hThread );
return true;
}
//-----------------------------------------------------------------------------
// <ThreadImpl::Sleep>
// Cause thread to sleep for the specified number of milliseconds
//-----------------------------------------------------------------------------
void ThreadImpl::Sleep
(
uint32 _millisecs
)
{
::Sleep(_millisecs);
}
//-----------------------------------------------------------------------------
// <ThreadImpl::Terminate>
// Force the thread to stop
//-----------------------------------------------------------------------------
bool ThreadImpl::Terminate
(
)
{
if( !m_bIsRunning )
{
return false;
}
// This can cause all sorts of trouble if the thread is holding a lock.
TerminateThread( m_hThread, 0 );
m_hThread = INVALID_HANDLE_VALUE;
return true;
}
//-----------------------------------------------------------------------------
// <ThreadImpl::IsSignalled>
// Test whether the thread has completed
//-----------------------------------------------------------------------------
bool ThreadImpl::IsSignalled
(
)
{
return !m_bIsRunning;
}
//-----------------------------------------------------------------------------
// <ThreadImpl::ThreadProc>
// Entry point for running a function on this thread
//-----------------------------------------------------------------------------
DWORD WINAPI ThreadImpl::ThreadProc
(
void* _pArg
)
{
ThreadImpl* pImpl = (ThreadImpl*)_pArg;
pImpl->Run();
return 0;
}
//-----------------------------------------------------------------------------
// <ThreadImpl::Run>
// Entry point for running a function on this thread
//-----------------------------------------------------------------------------
void ThreadImpl::Run
(
)
{
m_bIsRunning = true;
m_pfnThreadProc( m_exitEvent, m_context );
m_bIsRunning = false;
// Let any watchers know that the thread has finished running.
m_owner->Notify();
}
@@ -0,0 +1,71 @@
//-----------------------------------------------------------------------------
//
// ThreadImpl.h
//
// Windows implementation of a cross-platform thread
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _ThreadImpl_H
#define _ThreadImpl_H
#include <string>
#include <windows.h>
#include "../Thread.h"
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;
HANDLE m_hThread;
Event* m_exitEvent;
Thread::pfnThreadProc_t m_pfnThreadProc;
void* m_context;
bool m_bIsRunning;
string m_name;
};
} // namespace OpenZWave
#endif //_ThreadImpl_H
@@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
//
// TimeStampImpl.h
//
// Cross-platform TimeStampImpl
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include <string>
#include <windows.h>
#include "../../Defs.h"
#include "TimeStampImpl.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <TimeStampImpl::TimeStampImpl>
// Constructor
//-----------------------------------------------------------------------------
TimeStampImpl::TimeStampImpl
(
)
{
SetTime(0);
}
//-----------------------------------------------------------------------------
// <TimeStampImpl::~TimeStampImpl>
// Destructor
//-----------------------------------------------------------------------------
TimeStampImpl::~TimeStampImpl
(
)
{
}
//-----------------------------------------------------------------------------
// <TimeStampImpl::SetTime>
// 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;
}
//-----------------------------------------------------------------------------
// <TimeStampImpl::TimeRemaining>
// 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 );
}
//-----------------------------------------------------------------------------
// <TimeStampImpl::GetAsString>
// 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;
}
//-----------------------------------------------------------------------------
// <TimeStampImpl::operator->
// 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 );
}
@@ -0,0 +1,88 @@
//-----------------------------------------------------------------------------
//
// TimeStampImpl.h
//
// Windows implementation of a TimeStamp
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#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
@@ -0,0 +1,134 @@
//-----------------------------------------------------------------------------
//
// WaitImpl.cpp
//
// Windows implementation of an abstract base class for objects we
// want to be able to wait for.
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#include "../../Defs.h"
#include "../Wait.h"
#include "WaitImpl.h"
#include "../Log.h"
using namespace OpenZWave;
//-----------------------------------------------------------------------------
// <WaitImpl::WaitImpl>
// Constructor
//-----------------------------------------------------------------------------
WaitImpl::WaitImpl
(
Wait* _owner
):
m_owner( _owner )
{
InitializeCriticalSection( &m_criticalSection );
}
//-----------------------------------------------------------------------------
// <WaitImpl::~WaitImpl>
// Destructor
//-----------------------------------------------------------------------------
WaitImpl::~WaitImpl
(
)
{
DeleteCriticalSection( &m_criticalSection );
}
//-----------------------------------------------------------------------------
// <WaitImpl::AddWatcher>
// 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 );
}
}
//-----------------------------------------------------------------------------
// <WaitImpl::RemoveWatcher>
// Remove a watcher from our object.
//-----------------------------------------------------------------------------
bool WaitImpl::RemoveWatcher
(
Wait::pfnWaitNotification_t _callback,
void* _context
)
{
bool res = false;
EnterCriticalSection( &m_criticalSection );
for( list<Watcher>::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;
}
//-----------------------------------------------------------------------------
// <WaitImpl::Notify>
// Notify all the watchers that the object has become signalled
//-----------------------------------------------------------------------------
void WaitImpl::Notify
(
)
{
EnterCriticalSection( &m_criticalSection );
for( list<Watcher>::iterator it=m_watchers.begin(); it!=m_watchers.end(); ++it )
{
Watcher const& watcher = *it;
watcher.m_callback( watcher.m_context );
}
LeaveCriticalSection( &m_criticalSection );
}
@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------------
//
// WaitImpl.h
//
// Windows implementation of a base class for objects we
// want to be able to wait for.
//
// Copyright (c) 2010 Mal Lansell <mal@lansell.org>
// 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 <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
#ifndef _WaitImpl_H
#define _WaitImpl_H
#include <windows.h>
#include <list>
#include "../../Defs.h"
#include "../Ref.h"
#include "../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<Watcher> m_watchers;
Wait* m_owner;
CRITICAL_SECTION m_criticalSection;
};
} // namespace OpenZWave
#endif //_WaitImpl_H