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,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;
}