void * deviceLevel1WriteThread(void *pData) { // Level1MsgOutList::compatibility_iterator nodeLevel1; CDeviceItem *pDevItem = (CDeviceItem *)pData; if (NULL == pDevItem) { syslog(LOG_CRIT, "deviceLevel1WriteThread quitting due to NULL DevItem object."); return NULL; } // Blocking send method must have been found if (NULL == pDevItem->m_proc_CanalBlockingSend) return NULL; while (!pDevItem->m_bQuit) { // Wait until there is something to send if ((-1 == vscp_sem_wait( &pDevItem->m_pClientItem->m_semClientInputQueue, 500)) && errno == ETIMEDOUT) { continue; } if (pDevItem->m_pClientItem->m_clientInputQueue.size()) { pthread_mutex_lock( &pDevItem->m_pClientItem->m_mutexClientInputQueue); vscpEvent *pqueueEvent = pDevItem->m_pClientItem->m_clientInputQueue.front(); pDevItem->m_pClientItem->m_clientInputQueue.pop_front(); pthread_mutex_unlock( &pDevItem->m_pClientItem->m_mutexClientInputQueue); // Trow away event if Level II and Level I interface if ((CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1 == pDevItem->m_pClientItem->m_type) && (pqueueEvent->vscp_class > 512)) { vscp_deleteVSCPevent(pqueueEvent); continue; } canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == pDevItem->m_proc_CanalBlockingSend( pDevItem->m_openHandle, &canalMsg, 300)) { vscp_deleteVSCPevent(pqueueEvent); } else { // Give it another try sem_post(&pDevItem->m_pCtrlObject->m_semClientOutputQueue); } } // events in queue } // while return NULL; }
bool CVSCPBTDetectWrkTread::sendEvent( vscpEventEx& eventEx ) { vscpEvent *pEvent = new vscpEvent(); if ( NULL != pEvent ) { if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) { // OK send the event m_pObj->m_mutexReceiveQueue.Lock(); m_pObj->m_receiveList.push_back( pEvent ); m_pObj->m_semReceiveQueue.Post(); m_pObj->m_mutexReceiveQueue.Unlock(); } else { vscp_deleteVSCPevent( pEvent ); #ifndef WIN32 syslog( LOG_ERR, "%s", ( const char * ) "Faild to convert event." ); #endif return false; } } return true; }
extern "C" int VSCPBlockingReceive( long handle, vscpEvent *pEvent, unsigned long timeout ) { int rv = 0; // Check pointer if ( NULL == pEvent ) return CANAL_ERROR_PARAMETER; CVSCPBTDetect *pdrvObj = theApp->getDriverObject( handle ); if ( NULL == pdrvObj ) return CANAL_ERROR_MEMORY; if ( wxSEMA_TIMEOUT == pdrvObj->m_semReceiveQueue.WaitTimeout( timeout ) ) { return CANAL_ERROR_TIMEOUT; } pdrvObj->m_mutexReceiveQueue.Lock(); vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front(); pdrvObj->m_receiveList.pop_front(); pdrvObj->m_mutexReceiveQueue.Unlock(); if ( NULL == pLocalEvent ) return CANAL_ERROR_MEMORY; vscp_copyVSCPEvent( pEvent, pLocalEvent ); vscp_deleteVSCPevent( pLocalEvent ); return CANAL_ERROR_SUCCESS; }
extern "C" int VSCPBlockingReceive(long handle, vscpEvent *pEvent, unsigned long timeout) { int rv = 0; // Check pointer if ( NULL == pEvent) return CANAL_ERROR_PARAMETER; CRpiLCD *pdrvObj = theApp.getDriverObject(handle); if (NULL == pdrvObj) return CANAL_ERROR_MEMORY; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = timeout * 1e6; if ( ETIMEDOUT == sem_timedwait( &pdrvObj->m_semaphore_ReceiveQueue, &ts ) ) { return CANAL_ERROR_TIMEOUT; } pthread_mutex_lock( &pdrvObj->m_mutex_ReceiveQueue ); vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front(); pdrvObj->m_receiveList.pop_front(); pthread_mutex_unlock( &pdrvObj->m_mutex_ReceiveQueue ); if ( NULL == pLocalEvent ) return CANAL_ERROR_MEMORY; vscp_copyVSCPEvent( pEvent, pLocalEvent ); vscp_deleteVSCPevent( pLocalEvent ); return CANAL_ERROR_SUCCESS; }
extern "C" int VSCPBlockingReceive(long handle, vscpEvent *pEvent, unsigned long timeout) { int rv = 0; // Check pointer if ( NULL == pEvent) return CANAL_ERROR_PARAMETER; CTcpipLink *pdrvObj = theApp.getDriverObject(handle); if (NULL == pdrvObj) return CANAL_ERROR_MEMORY; if ( wxSEMA_TIMEOUT == pdrvObj->m_semReceiveQueue.WaitTimeout( timeout ) ) { return CANAL_ERROR_TIMEOUT; } //VSCPEVENTLIST_RECEIVE::compatibility_iterator nodeClient; pdrvObj->m_mutexReceiveQueue.Lock(); //nodeClient = pdrvObj->m_receiveQueue.GetFirst(); //vscpEvent *pLocalEvent = nodeClient->GetData(); vscpEvent *pLocalEvent = pdrvObj->m_receiveList.front(); pdrvObj->m_receiveList.pop_front(); pdrvObj->m_mutexReceiveQueue.Unlock(); if (NULL == pLocalEvent) return CANAL_ERROR_MEMORY; vscp_copyVSCPEvent( pEvent, pLocalEvent ); //pdrvObj->m_receiveQueue.DeleteNode(nodeClient); vscp_deleteVSCPevent( pLocalEvent ); return CANAL_ERROR_SUCCESS; }
CClientItem::~CClientItem() { CLIENTEVENTLIST::iterator iter; for ( iter = m_clientInputQueue.begin(); iter != m_clientInputQueue.end(); ++iter ) { vscpEvent *pEvent = *iter; vscp_deleteVSCPevent( pEvent ); } m_clientInputQueue.Clear(); }
void *deviceCanalWriteThread::Entry() { CanalMsgOutList::compatibility_iterator nodeCanal; // Must be a valid main object pointer if (NULL == m_pMainThreadObj) return NULL; // Blocking send method must have been found if (NULL == m_pMainThreadObj->m_pDeviceItem->m_proc_CanalBlockingSend) return NULL; while (!TestDestroy() && !m_bQuit) { // Wait until there is something to send if (wxSEMA_TIMEOUT == m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_semClientInputQueue.WaitTimeout(500)) { continue; } CLIENTEVENTLIST::compatibility_iterator nodeClient; if (m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetCount()) { m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Lock(); nodeClient = m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetFirst(); vscpEvent *pqueueEvent = nodeClient->GetData(); m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Unlock(); canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == m_pMainThreadObj->m_pDeviceItem->m_proc_CanalBlockingSend( m_pMainThreadObj->m_pDeviceItem->m_openHandle, &canalMsg, 300)) { // Remove the node vscp_deleteVSCPevent(pqueueEvent); m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient); } else { // Give it another try m_pMainThreadObj->m_pCtrlObject->m_semClientOutputQueue.Post(); } } // events in queue } // while return NULL; }
void *deviceLevel2ReceiveThread::Entry() { vscpEvent *pEvent; // Must be a valid main object pointer if (NULL == m_pMainThreadObj) return NULL; int rv; while (!TestDestroy() && !m_bQuit) { pEvent = new vscpEvent; if (NULL == pEvent) continue; rv = m_pMainThreadObj->m_pDeviceItem->m_proc_VSCPBlockingReceive( m_pMainThreadObj->m_pDeviceItem->m_openHandle, pEvent, 500); if ((CANAL_ERROR_SUCCESS != rv) || (NULL == pEvent)) { delete pEvent; continue; } // Identify ourselves pEvent->obid = m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_clientID; // If timestamp is zero we set it here if ( 0 == pEvent->timestamp ) { pEvent->timestamp = vscp_makeTimeStamp(); } // If no GUID is set, // - Set driver GUID if define // - Set interface GUID if no driver GUID defined. uint8_t ifguid[16]; // Save nickname uint8_t nickname_msb = pEvent->GUID[14]; uint8_t nickname_lsb = pEvent->GUID[15]; // Set if to use memcpy( ifguid, pEvent->GUID, 16 ); ifguid[14] = 0; ifguid[15] = 0; // If if is set to zero use interface id if ( vscp_isGUIDEmpty( ifguid ) ) { // Set driver GUID if set if ( !m_pMainThreadObj->m_pDeviceItem->m_interface_guid.isNULL() ) { m_pMainThreadObj->m_pDeviceItem->m_interface_guid.writeGUID( pEvent->GUID ); } else { // If no driver GUID set use interface GUID m_pMainThreadObj->m_pDeviceItem->m_pClientItem->m_guid.writeGUID( pEvent->GUID ); } // Preserve nickname pEvent->GUID[14] = nickname_msb; pEvent->GUID[15] = nickname_lsb; } // There must be room in the receive queue (even if rom (or whisky) has been better) if (m_pMainThreadObj->m_pCtrlObject->m_maxItemsInClientReceiveQueue > m_pMainThreadObj->m_pCtrlObject->m_clientOutputQueue.GetCount()) { m_pMainThreadObj->m_pCtrlObject->m_mutexClientOutputQueue.Lock(); m_pMainThreadObj->m_pCtrlObject->m_clientOutputQueue.Append(pEvent); m_pMainThreadObj->m_pCtrlObject->m_semClientOutputQueue.Post(); m_pMainThreadObj->m_pCtrlObject->m_mutexClientOutputQueue.Unlock(); } else { if (NULL == pEvent) vscp_deleteVSCPevent(pEvent); } } return NULL; }
void *deviceThread::Entry() { // Must have a valid pointer to the device item if (NULL == m_pDeviceItem) return NULL; // Must have a valid pointer to the control object if (NULL == m_pCtrlObject) return NULL; // We need to create a clientobject and add this object to the list m_pDeviceItem->m_pClientItem = new CClientItem; if (NULL == m_pDeviceItem->m_pClientItem) { return NULL; } // This is now an active Client m_pDeviceItem->m_pClientItem->m_bOpen = true; if ( VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel ) { m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2; } else { m_pDeviceItem->m_pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1; } m_pDeviceItem->m_pClientItem->m_strDeviceName = m_pDeviceItem->m_strName; m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" Started at "); wxDateTime now = wxDateTime::Now(); m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISODate(); m_pDeviceItem->m_pClientItem->m_strDeviceName += _(" "); m_pDeviceItem->m_pClientItem->m_strDeviceName += now.FormatISOTime(); m_pCtrlObject->logMsg(m_pDeviceItem->m_pClientItem->m_strDeviceName + _("\n"), DAEMON_LOGMSG_DEBUG); // Add the client to the Client List m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->addClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); // Load dynamic library if (!m_wxdll.Load(m_pDeviceItem->m_strPath, wxDL_LAZY)) { m_pCtrlObject->logMsg(_("Unable to load dynamic library.\n") ); return NULL; } if (VSCP_DRIVER_LEVEL1 == m_pDeviceItem->m_driverLevel) { // Now find methods in library { wxString str; str = _("Loading level I driver: "); str += m_pDeviceItem->m_strName; str += _("\n"); m_pCtrlObject->logMsg(str); wxLogDebug(str); } // * * * * CANAL OPEN * * * * if (NULL == (m_pDeviceItem->m_proc_CanalOpen = (LPFNDLL_CANALOPEN) m_wxdll.GetSymbol(_T("CanalOpen")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalOpen.\n") ); return NULL; } // * * * * CANAL CLOSE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalClose = (LPFNDLL_CANALCLOSE) m_wxdll.GetSymbol(_T("CanalClose")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalClose.\n") ); return NULL; } // * * * * CANAL GETLEVEL * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetLevel = (LPFNDLL_CANALGETLEVEL) m_wxdll.GetSymbol(_T("CanalGetLevel")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetLevel.\n") ); return NULL; } // * * * * CANAL SEND * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSend = (LPFNDLL_CANALSEND) m_wxdll.GetSymbol(_T("CanalSend")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSend.\n") ); return NULL; } // * * * * CANAL DATA AVAILABLE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalDataAvailable = (LPFNDLL_CANALDATAAVAILABLE) m_wxdll.GetSymbol(_T("CanalDataAvailable")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalDataAvailable.\n") ); return NULL; } // * * * * CANAL RECEIVE * * * * if (NULL == (m_pDeviceItem->m_proc_CanalReceive = (LPFNDLL_CANALRECEIVE) m_wxdll.GetSymbol(_T("CanalReceive")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalReceive.\n") ); return NULL; } // * * * * CANAL GET STATUS * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetStatus = (LPFNDLL_CANALGETSTATUS) m_wxdll.GetSymbol(_T("CanalGetStatus")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatus.\n") ); return NULL; } // * * * * CANAL GET STATISTICS * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetStatistics = (LPFNDLL_CANALGETSTATISTICS) m_wxdll.GetSymbol(_T("CanalGetStatistics")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetStatistics.\n") ); return NULL; } // * * * * CANAL SET FILTER * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSetFilter = (LPFNDLL_CANALSETFILTER) m_wxdll.GetSymbol(_T("CanalSetFilter")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetFilter.\n") ); return NULL; } // * * * * CANAL SET MASK * * * * if (NULL == (m_pDeviceItem->m_proc_CanalSetMask = (LPFNDLL_CANALSETMASK) m_wxdll.GetSymbol(_T("CanalSetMask")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalSetMask.\n") ); return NULL; } // * * * * CANAL GET VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetVersion = (LPFNDLL_CANALGETVERSION) m_wxdll.GetSymbol(_T("CanalGetVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVersion.\n") ); return NULL; } // * * * * CANAL GET DLL VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetDllVersion = (LPFNDLL_CANALGETDLLVERSION) m_wxdll.GetSymbol(_T("CanalGetDllVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDllVersion.\n") ); return NULL; } // * * * * CANAL GET VENDOR STRING * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetVendorString = (LPFNDLL_CANALGETVENDORSTRING) m_wxdll.GetSymbol(_T("CanalGetVendorString")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetVendorString.\n") ); return NULL; } // ****************************** // Generation 2 Methods // ****************************** // * * * * CANAL BLOCKING SEND * * * * m_pDeviceItem->m_proc_CanalBlockingSend = NULL; if (m_wxdll.HasSymbol(_T("CanalBlockingSend"))) { if (NULL == (m_pDeviceItem->m_proc_CanalBlockingSend = (LPFNDLL_CANALBLOCKINGSEND) m_wxdll.GetSymbol(_T("CanalBlockingSend")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingSend. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalBlockingSend = NULL; } } else { m_pCtrlObject->logMsg(_T("CanalBlockingSend not available. \n\tNon blocking operations set.\n") ); } // * * * * CANAL BLOCKING RECEIVE * * * * m_pDeviceItem->m_proc_CanalBlockingReceive = NULL; if (m_wxdll.HasSymbol(_T("CanalBlockingReceive"))) { if (NULL == (m_pDeviceItem->m_proc_CanalBlockingReceive = (LPFNDLL_CANALBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("CanalBlockingReceive")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalBlockingReceive. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalBlockingReceive = NULL; } } else { m_pCtrlObject->logMsg(_T("CanalBlockingReceive not available. \n\tNon blocking operations set.\n")); } // * * * * CANAL GET DRIVER INFO * * * * m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL; if (m_wxdll.HasSymbol(_T("CanalGetDriverInfo"))) { if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo = (LPFNDLL_CANALGETDRIVERINFO) m_wxdll.GetSymbol(_T("CanalGetDriverInfo")))) { m_pCtrlObject->logMsg(_T("Unable to get dl entry for CanalGetDriverInfo. Probably Generation 1 driver.\n") ); m_pDeviceItem->m_proc_CanalGetdriverInfo = NULL; } } // Open the device m_pDeviceItem->m_openHandle = m_pDeviceItem->m_proc_CanalOpen((const char *) m_pDeviceItem->m_strParameter.mb_str(wxConvUTF8), m_pDeviceItem->m_DeviceFlags); // Check if the driver opened properly if (m_pDeviceItem->m_openHandle <= 0) { wxString errMsg = _T("Failed to open driver. Will not use it! \n\t[ ") + m_pDeviceItem->m_strName + _T(" ]\n"); m_pCtrlObject->logMsg( errMsg ); return NULL; } else { wxString wxstr = wxString::Format(_("Driver %s opended.\n"), (const char *)m_pDeviceItem->m_strName.mbc_str() ); m_pCtrlObject->logMsg( wxstr ); } // Get Driver Level m_pDeviceItem->m_driverLevel = m_pDeviceItem->m_proc_CanalGetLevel(m_pDeviceItem->m_openHandle); // * * * Level I Driver * * * // Check if blocking driver is available if (NULL != m_pDeviceItem->m_proc_CanalBlockingReceive) { // * * * * Blocking version * * * * ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// m_pwriteThread = new deviceCanalWriteThread; if (m_pwriteThread) { m_pwriteThread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_pwriteThread->Create())) { m_pwriteThread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_pwriteThread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device write worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to create device write worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread.\n") ); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// m_preceiveThread = new deviceCanalReceiveThread; if (m_preceiveThread) { m_preceiveThread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_preceiveThread->Create())) { m_preceiveThread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_preceiveThread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device receive worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.\n") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.\n") ); } // Just sit and wait until the end of the world as we know it... while (!m_pDeviceItem->m_bQuit) { wxSleep(1); } m_preceiveThread->m_bQuit = true; m_pwriteThread->m_bQuit = true; m_preceiveThread->Wait(); m_pwriteThread->Wait(); } else { // * * * * Non blocking version * * * * bool bActivity; while (!TestDestroy() && !m_pDeviceItem->m_bQuit) { bActivity = false; ///////////////////////////////////////////////////////////////////////////// // Receive from device // ///////////////////////////////////////////////////////////////////////////// canalMsg msg; if (m_pDeviceItem->m_proc_CanalDataAvailable(m_pDeviceItem->m_openHandle)) { if (CANAL_ERROR_SUCCESS == m_pDeviceItem->m_proc_CanalReceive(m_pDeviceItem->m_openHandle, &msg)) { bActivity = true; // There must be room in the receive queue if (m_pCtrlObject->m_maxItemsInClientReceiveQueue > m_pCtrlObject->m_clientOutputQueue.GetCount()) { vscpEvent *pvscpEvent = new vscpEvent; if (NULL != pvscpEvent) { // Convert CANAL message to VSCP event vscp_convertCanalToEvent( pvscpEvent, &msg, m_pDeviceItem->m_pClientItem->m_guid.m_id ); pvscpEvent->obid = m_pDeviceItem->m_pClientItem->m_clientID; m_pCtrlObject->m_mutexClientOutputQueue.Lock(); m_pCtrlObject->m_clientOutputQueue.Append(pvscpEvent); m_pCtrlObject->m_semClientOutputQueue.Post(); m_pCtrlObject->m_mutexClientOutputQueue.Unlock(); } } } } // data available // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Send messages (if any) in the outqueue // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Check if there is something to send if (m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetCount()) { bActivity = true; CLIENTEVENTLIST::compatibility_iterator nodeClient; m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Lock(); nodeClient = m_pDeviceItem->m_pClientItem->m_clientInputQueue.GetFirst(); vscpEvent *pqueueEvent = nodeClient->GetData(); m_pDeviceItem->m_pClientItem->m_mutexClientInputQueue.Unlock(); canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == m_pDeviceItem->m_proc_CanalSend(m_pDeviceItem->m_openHandle, &canalMsg)) { // Remove the node delete pqueueEvent; m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient); } else { // Another try //m_pCtrlObject->m_semClientOutputQueue.Post(); vscp_deleteVSCPevent(pqueueEvent); m_pDeviceItem->m_pClientItem->m_clientInputQueue.DeleteNode(nodeClient); } } // events if (!bActivity) { ::wxMilliSleep(100); } bActivity = false; } // while working - non blocking } // if blocking/non blocking // Close CANAL channel m_pDeviceItem->m_proc_CanalClose(m_pDeviceItem->m_openHandle); // Library is unloaded in destructor // Remove messages in the client queues m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); if (NULL != m_preceiveThread) { m_preceiveThread->Wait(); delete m_preceiveThread; } if (NULL != m_pwriteThread) { m_pwriteThread->Wait(); delete m_pwriteThread; } } else if (VSCP_DRIVER_LEVEL2 == m_pDeviceItem->m_driverLevel) { // Now find methods in library { wxString str; str = _("Loading level II driver: <"); str += m_pDeviceItem->m_strName; str += _(">"); str += _("\n"); m_pCtrlObject->logMsg(str); } // * * * * VSCP OPEN * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPOpen = (LPFNDLL_VSCPOPEN) m_wxdll.GetSymbol(_T("VSCPOpen")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPOpen.\n")); return NULL; } // * * * * VSCP CLOSE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPClose = (LPFNDLL_VSCPCLOSE) m_wxdll.GetSymbol(_T("VSCPClose")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPClose.\n")); return NULL; } // * * * * VSCP BLOCKINGSEND * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingSend = (LPFNDLL_VSCPBLOCKINGSEND) m_wxdll.GetSymbol(_T("VSCPBlockingSend")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingSend.\n")); return NULL; } // * * * * VSCP BLOCKINGRECEIVE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPBlockingReceive = (LPFNDLL_VSCPBLOCKINGRECEIVE) m_wxdll.GetSymbol(_T("VSCPBlockingReceive")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPBlockingReceive.\n")); return NULL; } // * * * * VSCP GETLEVEL * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetLevel = (LPFNDLL_VSCPGETLEVEL) m_wxdll.GetSymbol(_T("VSCPGetLevel")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetLevel.\n")); return NULL; } // * * * * VSCP GET DLL VERSION * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetDllVersion = (LPFNDLL_VSCPGETDLLVERSION) m_wxdll.GetSymbol(_T("VSCPGetDllVersion")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDllVersion.\n")); return NULL; } // * * * * VSCP GET VENDOR STRING * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetVendorString = (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetVendorString")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetVendorString.\n")); return NULL; } // * * * * VSCP GET DRIVER INFO * * * * if (NULL == (m_pDeviceItem->m_proc_CanalGetdriverInfo = (LPFNDLL_VSCPGETVENDORSTRING) m_wxdll.GetSymbol(_T("VSCPGetDriverInfo")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetDriverInfo.\n")); return NULL; } // * * * * VSCP GET WEB PAGE TEMPLATE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageTemplate = (LPFNDLL_VSCPGETWEBPAGETEMPLATE) m_wxdll.GetSymbol(_T("VSCPGetWebPageTemplate")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageTemplate.\n")); return NULL; } // * * * * VSCP GET WEB PAGE INFO * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPGetWebPageInfo = (LPFNDLL_VSCPGETWEBPAGEINFO) m_wxdll.GetSymbol(_T("VSCPGetWebPageInfo")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPGetWebPageInfo.\n")); return NULL; } // * * * * VSCP WEB PAGE UPDATE * * * * if (NULL == (m_pDeviceItem->m_proc_VSCPWebPageupdate = (LPFNDLL_VSCPWEBPAGEUPDATE) m_wxdll.GetSymbol(_T("VSCPWebPageupdate")))) { // Free the library m_pCtrlObject->logMsg(_T("Unable to get dl entry for VSCPWebPageupdate.\n")); return NULL; } m_pCtrlObject->logMsg(_("Discovered all methods\n")); // Username, password, host and port can be set in configuration file. Read in them here // if they are. wxString strHost(_("127.0.0.1:9598")); wxStringTokenizer tkz(m_pDeviceItem->m_strParameter, _(";")); if (tkz.HasMoreTokens()) { CVSCPVariable *pVar; // Get prefix wxString prefix = tkz.GetNextToken(); // Check if username is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_username")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); m_pCtrlObject->m_driverUsername = str; } } // Check if password is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_password")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); m_pCtrlObject->m_driverPassword = str; } } // Check if host is specified in the configuration file pVar = m_pCtrlObject->m_VSCP_Variables.find(m_pDeviceItem->m_strName + _("_host")); if (NULL != pVar) { wxString str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == pVar->getType()) { pVar->getValue( str ); strHost = str; } } } // Open up the driver m_pDeviceItem->m_openHandle = m_pDeviceItem->m_proc_VSCPOpen( m_pCtrlObject->m_driverUsername.mbc_str(), ( const char * )m_pCtrlObject->m_driverPassword.mbc_str(), ( const char * )strHost.mbc_str(), 0, ( const char * )m_pDeviceItem->m_strName.mbc_str(), ( const char * )m_pDeviceItem->m_strParameter.mbc_str() ); if ( 0 == m_pDeviceItem->m_openHandle ) { // Free the library m_pCtrlObject->logMsg( _T( "Unable to open the library.\n" ) ); return NULL; } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// m_pwriteLevel2Thread = new deviceLevel2WriteThread; if (m_pwriteLevel2Thread) { m_pwriteLevel2Thread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_pwriteLevel2Thread->Create())) { m_pwriteLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_pwriteLevel2Thread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device write worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to create device write worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device write worker thread.")); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// m_preceiveLevel2Thread = new deviceLevel2ReceiveThread; if (m_preceiveLevel2Thread) { m_preceiveLevel2Thread->m_pMainThreadObj = this; wxThreadError err; if (wxTHREAD_NO_ERROR == (err = m_preceiveLevel2Thread->Create())) { m_preceiveLevel2Thread->SetPriority(WXTHREAD_MAX_PRIORITY); if (wxTHREAD_NO_ERROR != (err = m_preceiveLevel2Thread->Run())) { m_pCtrlObject->logMsg(_("Unable to run device receive worker thread.")); } } else { m_pCtrlObject->logMsg(_("Unable to create device receive worker thread.") ); } } else { m_pCtrlObject->logMsg(_("Unable to allocate memory for device receive worker thread.") ); } // Just sit and wait until the end of the world as we know it... while (!TestDestroy() && !m_pDeviceItem->m_bQuit) { wxSleep(200); } m_preceiveLevel2Thread->m_bQuit = true; m_pwriteLevel2Thread->m_bQuit = true; // Close channel m_pDeviceItem->m_proc_VSCPClose(m_pDeviceItem->m_openHandle); // Library is unloaded in destructor // Remove messages in the client queues m_pCtrlObject->m_wxClientMutex.Lock(); m_pCtrlObject->removeClient(m_pDeviceItem->m_pClientItem); m_pCtrlObject->m_wxClientMutex.Unlock(); if (NULL != m_preceiveLevel2Thread) { m_preceiveLevel2Thread->Wait(); delete m_preceiveLevel2Thread; } if (NULL != m_pwriteLevel2Thread) { m_pwriteLevel2Thread->Wait(); delete m_pwriteLevel2Thread; } } // // ===================================================================================== // return NULL; }
static void ev_handler( struct ns_connection *nc, int ev, void *p ) { struct ns_mqtt_message *msg = ( struct ns_mqtt_message * )p; Cmqttobj *pmqttobj = ( Cmqttobj *)nc->mgr->user_data; switch ( ev ) { case NS_CONNECT: ns_set_protocol_mqtt( nc ); ns_send_mqtt_handshake( nc, "vscpd" ); break; case NS_MQTT_CONNACK: if ( msg->connack_ret_code != NS_MQTT_CONNACK_ACCEPTED ) { printf( "Got mqtt connection error: %d\n", msg->connack_ret_code ); pmqttobj->m_bQuit = true; return; } pmqttobj->m_bConnected = true; if ( pmqttobj->m_bSubscribe ) { ns_mqtt_subscribe( nc, pmqttobj->m_topic_list, 1, 42 ); } else { ; } break; case NS_MQTT_PUBACK: printf( "Message publishing acknowledged (msg_id: %d)\n", msg->message_id ); break; case NS_MQTT_SUBACK: printf( "Subscription acknowledged, forwarding to '/test'\n" ); break; case NS_MQTT_PUBLISH: { printf( "Got incoming message %s: %.*s\n", msg->topic, ( int )msg->payload.len, msg->payload.p ); vscpEventEx eventEx; if ( !strcmp( msg->topic, pmqttobj->m_topic.ToAscii() ) ) { wxString str = wxString::FromAscii( ( const char * )msg->payload.p ); if ( vscp_setVscpEventExFromString( &eventEx, str ) ) { vscpEvent *pEvent = new vscpEvent; if ( NULL != pEvent ) { pEvent->sizeData = 0; pEvent->pdata = NULL; if ( vscp_doLevel2FilterEx( &eventEx, &pmqttobj->m_vscpfilter ) ) { if ( vscp_convertVSCPfromEx( pEvent, &eventEx ) ) { pmqttobj->m_mutexReceiveQueue.Lock(); pmqttobj->m_receiveList.push_back( pEvent ); pmqttobj->m_semReceiveQueue.Post(); pmqttobj->m_mutexReceiveQueue.Unlock(); } else { } } else { vscp_deleteVSCPevent( pEvent ); } } } } } break; case NS_CLOSE: printf( "Connection closed\n" ); pmqttobj->m_bConnected = false; pmqttobj->m_bQuit = true; } }
void * deviceThread(void *pData) { const char *dlsym_error; CDeviceItem *pDevItem = (CDeviceItem *)pData; if (NULL == pDevItem) { syslog(LOG_CRIT, "No device item defined. Aborting device thread!"); return NULL; } // Must have a valid pointer to the control object CControlObject *pCtrlObj = pDevItem->m_pCtrlObject; if (NULL == pCtrlObj) { syslog(LOG_CRIT, "No control object defined. Aborting device thread!"); return NULL; } // We need to create a clientobject and add this object to the list CClientItem *pClientItem = pDevItem->m_pClientItem = new CClientItem; if (NULL == pClientItem) { return NULL; } // This is now an active Client pClientItem->m_bOpen = true; if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1; } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL2; } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) { pClientItem->m_type = CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL3; } char datebuf[80]; time_t now = time(NULL); vscp_getTimeString(datebuf, sizeof(datebuf), &now); pClientItem->m_strDeviceName = pDevItem->m_strName; pClientItem->m_strDeviceName += "|Started at "; pClientItem->m_strDeviceName += datebuf; syslog(LOG_DEBUG, "Devicethread: Starting %s", pClientItem->m_strDeviceName.c_str()); // Add the client to the Client List pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList); if (!pCtrlObj->addClient(pClientItem, pDevItem->m_interface_guid.getClientID())) { // Failed to add client delete pDevItem->m_pClientItem; pDevItem->m_pClientItem = NULL; pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); syslog(LOG_ERR, "Devicethread: Failed to add client. Terminating thread."); return NULL; } pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); // Client now have GUID set to server GUID + channel id // If device has a non NULL GUID replace the client GUID preserving // the channel id with that GUID if (!pClientItem->m_guid.isNULL()) { memcpy( pClientItem->m_guid.m_id, pDevItem->m_interface_guid.getGUID(), 12); } void *hdll; if (VSCP_DRIVER_LEVEL3 != pDevItem->m_driverLevel) { // Load dynamic library hdll = dlopen(pDevItem->m_strPath.c_str(), RTLD_LAZY); if (!hdll) { syslog(LOG_ERR, "Devicethread: Unable to load dynamic library. path = %s", pDevItem->m_strPath.c_str()); return NULL; } } else { // Level III driver // Startup Level III driver std::string executable = pDevItem->m_strPath; pid_t pid = fork(); if (pid == -1) { syslog(LOG_ERR, "Failed to start level III driver %s (fork).", pDevItem->m_strName.c_str()); } else if (pid == 0) { // we're in child // Set process group to child process' pid. Then killing -pid // of the parent will kill the process and all of its children. setsid(); // Arguments: TODO // user // password // config parameters... // execvp( *argv, const_cast<char**>(argv) ); // Wait on child int status; waitpid(pid, &status, 0); } } if (VSCP_DRIVER_LEVEL1 == pDevItem->m_driverLevel) { // Now find methods in library syslog( LOG_INFO, "Loading level I driver: %s", pDevItem->m_strName.c_str()); // * * * * CANAL OPEN * * * * pDevItem->m_proc_CanalOpen = (LPFNDLL_CANALOPEN)dlsym(hdll, "CanalOpen"); const char *dlsym_error = dlerror(); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_DEBUG, "%s : Unable to get dl entry for CanalOpen.", pDevItem->m_strName.c_str()); return NULL; } // * * * * CANAL CLOSE * * * * pDevItem->m_proc_CanalClose = (LPFNDLL_CANALCLOSE)dlsym(hdll, "CanalClose"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalClose.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GETLEVEL * * * * pDevItem->m_proc_CanalGetLevel = (LPFNDLL_CANALGETLEVEL)dlsym(hdll, "CanalGetLevel"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetLevel.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SEND * * * * pDevItem->m_proc_CanalSend = (LPFNDLL_CANALSEND)dlsym(hdll, "CanalSend"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSend.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL DATA AVAILABLE * * * * pDevItem->m_proc_CanalDataAvailable = (LPFNDLL_CANALDATAAVAILABLE)dlsym(hdll, "CanalDataAvailable"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalDataAvailable.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL RECEIVE * * * * pDevItem->m_proc_CanalReceive = (LPFNDLL_CANALRECEIVE)dlsym(hdll, "CanalReceive"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalReceive.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET STATUS * * * * pDevItem->m_proc_CanalGetStatus = (LPFNDLL_CANALGETSTATUS)dlsym(hdll, "CanalGetStatus"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetStatus.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET STATISTICS * * * * pDevItem->m_proc_CanalGetStatistics = (LPFNDLL_CANALGETSTATISTICS)dlsym(hdll, "CanalGetStatistics"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetStatistics.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SET FILTER * * * * pDevItem->m_proc_CanalSetFilter = (LPFNDLL_CANALSETFILTER)dlsym(hdll, "CanalSetFilter"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSetFilter.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL SET MASK * * * * pDevItem->m_proc_CanalSetMask = (LPFNDLL_CANALSETMASK)dlsym(hdll, "CanalSetMask"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalSetMask.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET VERSION * * * * pDevItem->m_proc_CanalGetVersion = (LPFNDLL_CANALGETVERSION)dlsym(hdll, "CanalGetVersion"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetVersion.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET DLL VERSION * * * * pDevItem->m_proc_CanalGetDllVersion = (LPFNDLL_CANALGETDLLVERSION)dlsym(hdll, "CanalGetDllVersion"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetDllVersion.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // * * * * CANAL GET VENDOR STRING * * * * pDevItem->m_proc_CanalGetVendorString = (LPFNDLL_CANALGETVENDORSTRING)dlsym(hdll, "CanalGetVendorString"); dlsym_error = dlerror(); if (dlsym_error) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetVendorString.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } // ****************************** // Generation 2 Methods // ****************************** // * * * * CANAL BLOCKING SEND * * * * pDevItem->m_proc_CanalBlockingSend = (LPFNDLL_CANALBLOCKINGSEND)dlsym(hdll, "CanalBlockingSend"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalBlockingSend. Probably " "Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalBlockingSend = NULL; } // * * * * CANAL BLOCKING RECEIVE * * * * pDevItem->m_proc_CanalBlockingReceive = (LPFNDLL_CANALBLOCKINGRECEIVE)dlsym(hdll, "CanalBlockingReceive"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalBlockingReceive. " "Probably Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalBlockingReceive = NULL; } // * * * * CANAL GET DRIVER INFO * * * * pDevItem->m_proc_CanalGetdriverInfo = (LPFNDLL_CANALGETDRIVERINFO)dlsym(hdll, "CanalGetDriverInfo"); dlsym_error = dlerror(); if (dlsym_error) { syslog(LOG_ERR, "%s: Unable to get dl entry for CanalGetDriverInfo. " "Probably Generation 1 driver.", pDevItem->m_strName.c_str()); pDevItem->m_proc_CanalGetdriverInfo = NULL; } // Open the device pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen( (const char *)pDevItem->m_strParameter.c_str(), pDevItem->m_DeviceFlags); // Check if the driver opened properly if (pDevItem->m_openHandle <= 0) { syslog(LOG_ERR, "Failed to open driver. Will not use it! [%s] ", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Driver open.", pDevItem->m_strName.c_str()); } // Get Driver Level pDevItem->m_driverLevel = pDevItem->m_proc_CanalGetLevel(pDevItem->m_openHandle); // * * * Level I Driver * * * // Check if blocking driver is available if (NULL != pDevItem->m_proc_CanalBlockingReceive) { // * * * * Blocking version * * * * if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I blocking version.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level1WriteThread, NULL, deviceLevel1WriteThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device write worker thread.", pDevItem->m_strName.c_str()); // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen(); dlclose(hdll); return NULL; } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level1ReceiveThread, NULL, deviceLevel1ReceiveThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device read worker thread.", pDevItem->m_strName.c_str()); pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level1WriteThread, NULL); // pDevItem->m_openHandle = pDevItem->m_proc_CanalOpen(); dlclose(hdll); return NULL; } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } // Signal worker threads to quit pDevItem->m_bQuit = true; if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I work loop ended.", pDevItem->m_strName.c_str()); } // Wait for workerthreads to abort pthread_join(pDevItem->m_level1WriteThread, NULL); pthread_join(pDevItem->m_level1ReceiveThread, NULL); } else { // * * * * Non blocking version * * * * if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I NON Blocking version.", pDevItem->m_strName.c_str()); } bool bActivity; while (pDevItem->m_bQuit) { bActivity = false; ///////////////////////////////////////////////////////////////////////////// // Receive from device ///////////////////////////////////////////////////////////////////////////// canalMsg msg; if (pDevItem->m_proc_CanalDataAvailable( pDevItem->m_openHandle)) { if (CANAL_ERROR_SUCCESS == pDevItem->m_proc_CanalReceive(pDevItem->m_openHandle, &msg)) { bActivity = true; // There must be room in the receive queue if (pCtrlObj->m_maxItemsInClientReceiveQueue > pCtrlObj->m_clientOutputQueue.size()) { vscpEvent *pvscpEvent = new vscpEvent; if (NULL != pvscpEvent) { // Set driver GUID if set /*if ( pDevItem->m_interface_guid.isNULL() ) { pDevItem->m_interface_guid.writeGUID( pvscpEvent->GUID ); } else { // If no driver GUID set use interface GUID pItem->m_guid.writeGUID( pvscpEvent->GUID ); }*/ // Convert CANAL message to VSCP event vscp_convertCanalToEvent( pvscpEvent, &msg, pClientItem->m_guid.m_id); pvscpEvent->obid = pClientItem->m_clientID; pthread_mutex_lock( &pCtrlObj->m_mutexClientOutputQueue); pCtrlObj->m_clientOutputQueue.push_back( pvscpEvent); sem_post(&pCtrlObj->m_semClientOutputQueue); pthread_mutex_unlock( &pCtrlObj->m_mutexClientOutputQueue); } } } } // data available // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Send messages (if any) in the output queue // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Check if there is something to send if (pClientItem->m_clientInputQueue.size()) { bActivity = true; std::deque<vscpEvent *>::iterator it; pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue); vscpEvent *pqueueEvent = pClientItem->m_clientInputQueue.front(); pthread_mutex_lock(&pClientItem->m_mutexClientInputQueue); // Trow away Level II event on Level I interface if ((CLIENT_ITEM_INTERFACE_TYPE_DRIVER_LEVEL1 == pClientItem->m_type) && (pqueueEvent->vscp_class > 512)) { // Remove the event and the node pClientItem->m_clientInputQueue.pop_front(); syslog(LOG_ERR, "Level II event on Level I queue thrown away. " "class=%d, type=%d", pqueueEvent->vscp_class, pqueueEvent->vscp_type); vscp_deleteVSCPevent(pqueueEvent); continue; } canalMsg canalMsg; vscp_convertEventToCanal(&canalMsg, pqueueEvent); if (CANAL_ERROR_SUCCESS == pDevItem->m_proc_CanalSend(pDevItem->m_openHandle, &canalMsg)) { // Remove the event and the node pClientItem->m_clientInputQueue.pop_front(); delete pqueueEvent; } else { // Another try // pCtrlObj->m_semClientOutputQueue.Post(); // vscp_deleteVSCPevent(pqueueEvent); TODO ???? } } // events if (!bActivity) { usleep(100000); // 100 ms } bActivity = false; } // while working - non blocking } // if blocking/non blocking if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Work loop ended.", pDevItem->m_strName.c_str()); } // Close CANAL channel pDevItem->m_proc_CanalClose(pDevItem->m_openHandle); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level I Closed.", pDevItem->m_strName.c_str()); } level1_driver_exit: pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level1WriteThread, NULL); pthread_join(pDevItem->m_level1ReceiveThread, NULL); dlclose(hdll); } else if (VSCP_DRIVER_LEVEL2 == pDevItem->m_driverLevel) { // Now find methods in library syslog(LOG_INFO, "Loading level II driver: <%s>", pDevItem->m_strName.c_str()); // * * * * VSCP OPEN * * * * if (NULL == (pDevItem->m_proc_VSCPOpen = (LPFNDLL_VSCPOPEN)dlsym(hdll, "VSCPOpen"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPOpen.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP CLOSE * * * * if (NULL == (pDevItem->m_proc_VSCPClose = (LPFNDLL_VSCPCLOSE)dlsym(hdll, "VSCPClose"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPClose.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP BLOCKINGSEND * * * * if (NULL == (pDevItem->m_proc_VSCPBlockingSend = (LPFNDLL_VSCPBLOCKINGSEND)dlsym(hdll, "VSCPBlockingSend"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPBlockingSend.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP BLOCKINGRECEIVE * * * * if (NULL == (pDevItem->m_proc_VSCPBlockingReceive = (LPFNDLL_VSCPBLOCKINGRECEIVE)dlsym( hdll, "VSCPBlockingReceive"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPBlockingReceive.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GETLEVEL * * * * if (NULL == (pDevItem->m_proc_VSCPGetLevel = (LPFNDLL_VSCPGETLEVEL)dlsym(hdll, "VSCPGetLevel"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetLevel.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET DLL VERSION * * * * if (NULL == (pDevItem->m_proc_VSCPGetDllVersion = (LPFNDLL_VSCPGETDLLVERSION)dlsym(hdll, "VSCPGetDllVersion"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetDllVersion.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET VENDOR STRING * * * * if (NULL == (pDevItem->m_proc_VSCPGetVendorString = (LPFNDLL_VSCPGETVENDORSTRING)dlsym( hdll, "VSCPGetVendorString"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetVendorString.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET DRIVER INFO * * * * if (NULL == (pDevItem->m_proc_CanalGetdriverInfo = (LPFNDLL_VSCPGETVENDORSTRING)dlsym(hdll, "VSCPGetDriverInfo"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetDriverInfo.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET WEB PAGE TEMPLATE * * * * if (NULL == (pDevItem->m_proc_VSCPGetWebPageTemplate = (LPFNDLL_VSCPGETWEBPAGETEMPLATE)dlsym( hdll, "VSCPGetWebPageTemplate"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetWebPageTemplate.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP GET WEB PAGE INFO * * * * if (NULL == (pDevItem->m_proc_VSCPGetWebPageInfo = (LPFNDLL_VSCPGETWEBPAGEINFO)dlsym(hdll, "VSCPGetWebPageInfo"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPGetWebPageInfo.", pDevItem->m_strName.c_str()); return NULL; } // * * * * VSCP WEB PAGE UPDATE * * * * if (NULL == (pDevItem->m_proc_VSCPWebPageupdate = (LPFNDLL_VSCPWEBPAGEUPDATE)dlsym(hdll, "VSCPWebPageupdate"))) { // Free the library syslog(LOG_ERR, "%s: Unable to get dl entry for VSCPWebPageupdate.", pDevItem->m_strName.c_str()); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: Discovered all methods\n", pDevItem->m_strName.c_str()); } // Username, password, host and port can be set in configuration file. // Read in them here if they are. std::string strHost("127.0.0.1"); short port = 9598; std::deque<std::string> tokens; vscp_split(tokens, pDevItem->m_strParameter, ";"); if (false == tokens.empty()) { CVariable variable; // Get prefix std::string prefix = tokens.front(); tokens.pop_front(); // Check if username is specified in the configuration file CUserItem *pAdminUser = pDevItem->m_pCtrlObject->m_userList.getUser(USER_ID_ADMIN); if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_username", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); pCtrlObj->m_driverUsername = str; } } // Check if password is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_password", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); pCtrlObj->m_driverPassword = str; } } // Check if host is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_host", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_STRING == variable.getType()) { str = variable.getValue(); strHost = str; } } // Check if host is specified in the configuration file if (pCtrlObj->m_variables.find( pDevItem->m_strName + "_port", pAdminUser, variable)) { std::string str; if (VSCP_DAEMON_VARIABLE_CODE_INTEGER == variable.getType()) { str = variable.getValue(); port = vscp_readStringValue(str); } } } // Open up the driver pDevItem->m_openHandle = pDevItem->m_proc_VSCPOpen( pCtrlObj->m_driverUsername.c_str(), (const char *)pCtrlObj->m_driverPassword.c_str(), (const char *)strHost.c_str(), port, (const char *)pDevItem->m_strName.c_str(), (const char *)pDevItem->m_strParameter.c_str()); if (0 == pDevItem->m_openHandle) { // Free the library syslog(LOG_ERR, "%s: [Device tread] Unable to open VSCP " "driver (check username/password/path/" "rights). Possible additional info from driver " "in syslog.", pDevItem->m_strName.c_str()); return NULL; } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Open.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device write worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level2WriteThread, NULL, deviceLevel2WriteThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device Level II write worker thread.", pDevItem->m_strName.c_str()); dlclose(hdll); return NULL; // TODO close dll } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Write thread created.", pDevItem->m_strName.c_str()); } ///////////////////////////////////////////////////////////////////////////// // Device read worker thread ///////////////////////////////////////////////////////////////////////////// if (pthread_create(&pDevItem->m_level2ReceiveThread, NULL, deviceLevel2ReceiveThread, pDevItem)) { syslog(LOG_CRIT, "%s: Unable to run the device Level II read worker thread.", pDevItem->m_strName.c_str()); pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level2WriteThread, NULL); dlclose(hdll); return NULL; // TODO close dll, kill other thread } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Write thread created.", pDevItem->m_strName.c_str()); } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Closing.", pDevItem->m_strName.c_str()); } // Close channel pDevItem->m_proc_VSCPClose(pDevItem->m_openHandle); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Closed.", pDevItem->m_strName.c_str()); } level2_driver_exit: pDevItem->m_bQuit = true; pthread_join(pDevItem->m_level2WriteThread, NULL); pthread_join(pDevItem->m_level2ReceiveThread, NULL); // Unload dll dlclose(hdll); if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II Done waiting for threads.", pDevItem->m_strName.c_str()); } } else if (VSCP_DRIVER_LEVEL3 == pDevItem->m_driverLevel) { if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level III Start server loop.", pDevItem->m_strName.c_str()); } // Just sit and wait until the end of the world as we know it... while (!pDevItem->m_bQuit) { sleep(1); } if (pCtrlObj->m_debugFlags[0] & VSCP_DEBUG1_DRIVER) { syslog(LOG_DEBUG, "%s: [Device tread] Level II End server loop.", pDevItem->m_strName.c_str()); } } // Remove messages in the client queues pthread_mutex_lock(&pCtrlObj->m_clientList.m_mutexItemList); pCtrlObj->removeClient(pClientItem); pthread_mutex_unlock(&pCtrlObj->m_clientList.m_mutexItemList); return NULL; }
void * CWrkWriteThread::Entry() { pcap_t *fp; char errbuf[ PCAP_ERRBUF_SIZE ]; uint8_t packet[ 512 ]; // First log on to the host and get configuration // variables /* if (m_srv.doCmdOpen(m_pObj->m_host, m_pObj->m_port, m_pObj->m_username, m_pObj->m_password) <= 0) { return NULL; } // Find the channel id uint32_t ChannelID; m_srv.doCmdGetChannelID(&ChannelID); // We want to use our own Ethernet based GUID for this interface wxString strGUID; m_pObj->m_localGUIDrx.toString(strGUID); m_srv.doCmdSetGUID((const char *) strGUID.ToAscii()); */ // Open the adapter if ((fp = pcap_open_live(m_pObj->m_interface.ToAscii(), // name of the device 65536, // portion of the packet to capture. It doesn't matter in this case 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { //fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]); return NULL; } // Enter receive loop to start to log events //m_srv.doCmdEnterReceiveLoop(); int rv; vscpEvent event; while (!TestDestroy() && !m_pObj->m_bQuit) { if ( wxSEMA_TIMEOUT == m_pObj->m_semSendQueue.WaitTimeout(300)) continue; // Check if there is event(s) to send if ( m_pObj->m_sendList.size() ) { // Yes there are data to send m_pObj->m_mutexSendQueue.Lock(); vscpEvent *pEvent = m_pObj->m_sendList.front(); m_pObj->m_sendList.pop_front(); m_pObj->m_mutexSendQueue.Unlock(); if (NULL == pEvent) continue; // Class must be a Level I class or a Level II // mirror class /* if (pEvent->vscp_class < 512) { frame.can_id = getCANidFromVSCPevent(pEvent); frame.can_id |= CAN_EFF_FLAG; // Always extended if (0 != pEvent->sizeData) { frame.len = (pEvent->sizeData > 8 ? 8 : pEvent->sizeData); memcpy(frame.data, pEvent->pdata, frame.len); } } else if (pEvent->vscp_class < 1024) { pEvent->vscp_class -= 512; frame.can_id = getCANidFromVSCPevent(pEvent); frame.can_id |= CAN_EFF_FLAG; // Always extended if (0 != pEvent->sizeData) { frame.len = ((pEvent->sizeData - 16) > 8 ? 8 : pEvent->sizeData - 16); memcpy(frame.data, pEvent->pdata + 16, frame.len); } } */ // Set mac destination to broadcast ff:ff:ff:ff:ff:ff packet[ 0 ] = 0xff; packet[ 1 ] = 0xff; packet[ 2 ] = 0xff; packet[ 3 ] = 0xff; packet[ 4 ] = 0xff; packet[ 5 ] = 0xff; // set mac source to configured value - 6..11 memcpy(packet + 6, m_pObj->m_localMac, 6); // Set the type - always 0x2574 (9598) packet[ 12 ] = 0x25; packet[ 13 ] = 0x7e; // rawEthernet frame version packet[ 14 ] = 0x00; // Head packet[ 15 ] = (event.head & VSCP_HEADER_PRIORITY_MASK); packet[ 16 ] = 0x00; packet[ 17 ] = 0x00; packet[ 18 ] = 0x00; // LSB // VSCP sub source address For this interface it's 0x0000 packet[ 19 ] = 0x00; packet[ 20 ] = 0x00; // Timestamp uint32_t timestamp = event.timestamp; packet[ 21 ] = (timestamp & 0xff000000) >> 24; packet[ 22 ] = (timestamp & 0x00ff0000) >> 16; packet[ 23 ] = (timestamp & 0x0000ff00) >> 8; packet[ 24 ] = (timestamp & 0x000000ff); // obid uint32_t obid = event.obid; packet[ 25 ] = (obid & 0xff000000) >> 24; packet[ 26 ] = (obid & 0x00ff0000) >> 16; packet[ 27 ] = (obid & 0x0000ff00) >> 8; packet[ 28 ] = (obid & 0x000000ff); // VSCP Class uint16_t vscp_class = event.vscp_class; packet[ 29 ] = (vscp_class & 0xff00) >> 8; packet[ 30 ] = (vscp_class & 0xff); // VSCP Type uint16_t vscp_type = event.vscp_type; packet[ 31 ] = (vscp_type & 0xff00) >> 8; packet[ 32 ] = (vscp_type & 0xff); // Size packet[ 33 ] = event.sizeData >> 8; packet[ 34 ] = event.sizeData & 0xff; // VSCP Data memcpy(packet + 35, event.pdata, event.sizeData); // Send the packet if (0 != pcap_sendpacket(fp, packet, 35 + event.sizeData)) { //fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(fp)); // An error sending the frame - we do nothing // TODO: Send error frame back to daemon???? } // Remove the event m_pObj->m_mutexSendQueue.Lock(); vscp_deleteVSCPevent(pEvent); m_pObj->m_mutexSendQueue.Unlock(); } // Event received } // work loop
void * CWrkReadThread::Entry() { pcap_t *fp; char errbuf[ PCAP_ERRBUF_SIZE ]; //uint8_t packet[ 512 ]; // First log on to the host and get configuration // variables if (m_srv.doCmdOpen(m_pObj->m_host, m_pObj->m_username, m_pObj->m_password) <= 0) { return NULL; } // Find the channel id m_srv.doCmdGetChannelID(&m_pObj->m_ChannelIDtx); // It is possible that there is configuration data the server holds // that we need to read in. // We look for // prefix_interface Communication interface to work on // prefix_localmac MAC address to use for outgoing packets // prefix_filter to find a filter. A string is expected. // prefix_mask to find a mask. A string is expected. /* // Interface wxString varInterface; if (m_srv.getVariableString(m_pObj->m_prefix + _T("_interface"), &varInterface)) { m_pObj->m_interface = varInterface; } wxString varLocalMac; if (m_srv.getVariableString(m_pObj->m_prefix + _T("_localmac"), &varLocalMac)) { varLocalMac.MakeUpper(); wxStringTokenizer tkz(varLocalMac, ":\n"); for (int i = 0; i < 6; i++) { if (tkz.HasMoreTokens()) break; wxString str = _("0X") + tkz.GetNextToken(); m_pObj->m_localMac[ i ] = readStringValue(str); m_pObj->m_localGUIDtx.setAt((9 + i), m_pObj->m_localMac[ i ]); m_pObj->m_localGUIDrx.setAt((9 + i), m_pObj->m_localMac[ i ]); } } */ // We want to use our own Ethernet based GUID for this interface //wxString strGUID; //m_pObj->m_localGUIDtx.toString(strGUID); //m_srv.doCmdSetGUID((const char *) strGUID.ToAscii()); // Open the adapter if ((fp = pcap_open_live(m_pObj->m_interface.ToAscii(), // name of the device 65536, // portion of the packet to capture. It doesn't matter in this case 1, // promiscuous mode (nonzero means promiscuous) 1000, // read timeout errbuf // error buffer )) == NULL) { //fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]); return NULL; } int rv; struct pcap_pkthdr *header; const u_char *pkt_data; while (!TestDestroy() && !m_pObj->m_bQuit && (rv = pcap_next_ex(fp, &header, &pkt_data)) >= 0) { // Check for timeout if (0 == rv) continue; // Check if this is VSCP if ((0x25 == pkt_data[ 12 ]) && (0x7e == pkt_data[ 13 ])) { // We have a packet - send it as a VSCP event vscpEventEx eventex; eventex.head = pkt_data[ 15 ] & 0xe0; // Priority eventex.GUID[ 0 ] = 0xff; // Ethernet predefined GUID eventex.GUID[ 1 ] = 0xff; eventex.GUID[ 2 ] = 0xff; eventex.GUID[ 3 ] = 0xff; eventex.GUID[ 4 ] = 0xff; eventex.GUID[ 5 ] = 0xff; eventex.GUID[ 6 ] = 0xff; eventex.GUID[ 7 ] = 0xfe; eventex.GUID[ 8 ] = pkt_data[ 6 ]; // Source MAC address eventex.GUID[ 9 ] = pkt_data[ 7 ]; eventex.GUID[ 10 ] = pkt_data[ 8 ]; eventex.GUID[ 11 ] = pkt_data[ 9 ]; eventex.GUID[ 12 ] = pkt_data[ 10 ]; eventex.GUID[ 13 ] = pkt_data[ 11 ]; eventex.GUID[ 14 ] = pkt_data[ 19 ]; // Device sub address eventex.GUID[ 15 ] = pkt_data[ 20 ]; eventex.timestamp = (pkt_data[ 21 ] << 24) + (pkt_data[ 22 ] << 16) + (pkt_data[ 23 ] << 8) + pkt_data[ 24 ]; eventex.obid = (pkt_data[ 25 ] << 24) + (pkt_data[ 26 ] << 16) + (pkt_data[ 27 ] << 8) + pkt_data[ 28 ]; eventex.vscp_class = (pkt_data[ 29 ] << 8) + pkt_data[ 30 ]; eventex.vscp_type = (pkt_data[ 31 ] << 8) + pkt_data[ 32 ]; eventex.sizeData = (pkt_data[ 33 ] << 8) + pkt_data[ 34 ]; // If the packet is smaller then the set datasize just // disregard it if ((eventex.sizeData + 35) > (uint16_t) header->len) continue; for (int i = 0; i < eventex.sizeData; i++) { eventex.data[ i ] = pkt_data[ 35 + i ]; } vscpEvent *pEvent = new vscpEvent; if (NULL != pEvent) { vscp_convertVSCPfromEx(pEvent, &eventex); if (vscp_doLevel2FilterEx( &eventex, &m_pObj->m_vscpfilter)) { m_pObj->m_mutexReceiveQueue.Lock(); m_pObj->m_receiveList.push_back(pEvent); m_pObj->m_semReceiveQueue.Post(); m_pObj->m_mutexReceiveQueue.Unlock(); } else { vscp_deleteVSCPevent(pEvent); } } } } // work loop // Close listner pcap_close(fp); // Close the channel //m_srv.doCmdClose(); return NULL; }
void * threadWorker(void *pData) { CLogWrkThreadObj *pObj = (CLogWrkThreadObj *)pData; if (NULL == pObj) { syslog(LOG_CRIT, "No thread object supplied to worker thread. Aborting!"); return NULL; } // Check pointers if (NULL == pObj->m_pLog) { syslog(LOG_CRIT, "No valid logger object suppied to worker thread. Aborting!"); return NULL; } // First log on to the host and get configuration // variables if (VSCP_ERROR_SUCCESS == pObj->m_srv.doCmdOpen(pObj->m_pLog->m_host, pObj->m_pLog->m_username, pObj->m_pLog->m_password) <= 0) { return NULL; } // Find the channel id uint32_t ChannelID; pObj->m_srv.doCmdGetChannelID(&ChannelID); // It is possible that there is configuration data the server holds // that we need to read in. // We look for // prefix_filter to find a filter. A string is expected. // prefix_mask to find a mask. A string is expected. // prefix_path to overide the file path for the log file. A string is // expected. prefix_rewrite to override the overwrite flag. A bool is // expected. // Get filter data std::string varFilter; std::string varMask; std::string strFilter = pObj->m_pLog->m_prefix + std::string("_filter"); std::string strMask = pObj->m_pLog->m_prefix + std::string("_mask"); if ((VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableValue(strFilter, varFilter)) && (VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableValue(strMask, varMask))) { pObj->m_srv.doCmdFilter(varFilter, varMask); } // get overriden file path std::string strPath = pObj->m_pLog->m_prefix + std::string("_path"); std::string varPath; if (VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableValue(strPath, varPath)) { pObj->m_pLog->m_path = varPath; } std::string strRewrite = pObj->m_pLog->m_prefix + std::string("_rewrite"); bool bOverwrite; if (VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableBool(strRewrite, &bOverwrite)) { if (bOverwrite) { pObj->m_pLog->m_flags |= LOG_FILE_OVERWRITE; } else { pObj->m_pLog->m_flags &= ~LOG_FILE_OVERWRITE; } } bool bVSCPWorksFormat; std::string strVscpWorkdFmt = pObj->m_pLog->m_prefix + std::string("_vscpworksfmt"); if (VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableBool(strVscpWorkdFmt, &bVSCPWorksFormat)) { if (bVSCPWorksFormat) { pObj->m_pLog->m_flags |= LOG_FILE_VSCP_WORKS; } else { pObj->m_pLog->m_flags &= ~LOG_FILE_VSCP_WORKS; } } // XML setup std::string str; std::string strSetupXML; std::string strName = pObj->m_pLog->m_prefix + std::string("_setup"); if (VSCP_ERROR_SUCCESS == pObj->m_srv.getRemoteVariableValue(strName, strSetupXML, true)) { XML_Parser xmlParser = XML_ParserCreate("UTF-8"); XML_SetUserData(xmlParser, pObj->m_pLog); XML_SetElementHandler(xmlParser, startSetupParser, endSetupParser); int bytes_read; void *buff = XML_GetBuffer(xmlParser, XML_BUFF_SIZE); strncpy((char *)buff, strSetupXML.c_str(), strSetupXML.length()); bytes_read = strSetupXML.length(); if (!XML_ParseBuffer(xmlParser, bytes_read, bytes_read == 0)) { syslog(LOG_ERR, "Failed parse XML setup."); } XML_ParserFree(xmlParser); } // Close server connection pObj->m_srv.doCmdClose(); // Open the file if (!pObj->m_pLog->openFile()) return NULL; while (!pObj->m_pLog->m_bQuit) { // Wait for events if ((-1 == vscp_sem_wait(&pObj->m_pLog->m_semSendQueue, 500)) && errno == ETIMEDOUT) { continue; } if (pObj->m_pLog->m_sendList.size()) { pthread_mutex_lock(&pObj->m_pLog->m_mutexSendQueue); vscpEvent *pEvent = pObj->m_pLog->m_sendList.front(); pObj->m_pLog->m_sendList.pop_front(); pthread_mutex_unlock(&pObj->m_pLog->m_mutexSendQueue); if (NULL == pEvent) continue; pObj->m_pLog->writeEvent(pEvent); vscp_deleteVSCPevent(pEvent); pEvent = NULL; } // Event received } // Receive loop // Close the channel pObj->m_srv.doCmdClose(); return NULL; }
void * CSocketCanWorkerTread::Entry() { int sock; char devname[IFNAMSIZ + 1]; fd_set rdfs; struct timeval tv; struct sockaddr_can addr; struct ifreq ifr; struct cmsghdr *cmsg; struct canfd_frame frame; char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))]; const int canfd_on = 1; ::wxInitialize(); // Check pointers if (NULL == m_pObj) return NULL; strncpy(devname, m_pObj->m_interface.ToAscii(), sizeof(devname) - 1); #if DEBUG syslog(LOG_ERR, "CWriteSocketCanTread: Interface: %s\n", ifname); #endif while (!TestDestroy() && !m_pObj->m_bQuit) { sock = socket(PF_CAN, SOCK_RAW, CAN_RAW); if (sock < 0) { if (ENETDOWN == errno) { sleep(1); continue; } syslog(LOG_ERR, "%s", (const char *) "CReadSocketCanTread: Error while opening socket. Terminating!"); m_pObj->m_bQuit; continue; } strcpy(ifr.ifr_name, devname); ioctl(sock, SIOCGIFINDEX, &ifr); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; #ifdef DEBUG printf("using interface name '%s'.\n", ifr.ifr_name); #endif // try to switch the socket into CAN FD mode setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)); if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "%s", (const char *) "CReadSocketCanTread: Error in socket bind. Terminating!"); close(sock); sleep(2); continue; } bool bInnerLoop = true; while (!TestDestroy() && !m_pObj->m_bQuit && bInnerLoop) { FD_ZERO(&rdfs); FD_SET(sock, &rdfs); tv.tv_sec = 0; tv.tv_usec = 5000; // 5ms timeout int ret; if ( ( ret = select(sock + 1, &rdfs, NULL, NULL, &tv ) ) < 0) { // Error if (ENETDOWN == errno) { // We try to get contact with the net // again if it goes down bInnerLoop = false; } else { m_pObj->m_bQuit = true; } continue; } if ( ret ) { // There is data to read ret = read(sock, &frame, sizeof(struct can_frame)); if (ret < 0) { if (ENETDOWN == errno) { // We try to get contact with the net // again if it goes down bInnerLoop = false; sleep(2); } else { m_pObj->m_bQuit = true; } continue; } // Must be Extended if (!(frame.can_id & CAN_EFF_FLAG)) continue; // Mask of control bits frame.can_id &= CAN_EFF_MASK; vscpEvent *pEvent = new vscpEvent(); if (NULL != pEvent) { pEvent->pdata = new uint8_t[frame.len]; if (NULL == pEvent->pdata) { delete pEvent; continue; } // GUID will be set to GUID of interface // by driver interface with LSB set to nickname memset(pEvent->GUID, 0, 16); pEvent->GUID[VSCP_GUID_LSB] = frame.can_id & 0xff; // Set VSCP class pEvent->vscp_class = vscp_getVSCPclassFromCANALid(frame.can_id); // Set VSCP type pEvent->vscp_type = vscp_getVSCPtypeFromCANALid(frame.can_id); // Copy data if any pEvent->sizeData = frame.len; if (frame.len) { memcpy(pEvent->pdata, frame.data, frame.len); } if (vscp_doLevel2Filter(pEvent, &m_pObj->m_vscpfilter)) { m_pObj->m_mutexReceiveQueue.Lock(); //m_pObj->m_receiveQueue.Append(pEvent); m_pObj->m_receiveList.push_back(pEvent); m_pObj->m_semReceiveQueue.Post(); m_pObj->m_mutexReceiveQueue.Unlock(); } else { vscp_deleteVSCPevent(pEvent); } } } else { // Check if there is event(s) to send if (m_pObj->m_sendList.size() /*m_pObj->m_sendQueue.GetCount()*/) { // Yes there are data to send // So send it out on the CAN bus //VSCPEVENTLIST_SEND::compatibility_iterator nodeClient; m_pObj->m_mutexSendQueue.Lock(); //nodeClient = m_pObj->m_sendQueue.GetFirst(); vscpEvent *pEvent = m_pObj->m_sendList.front(); m_pObj->m_sendList.pop_front(); m_pObj->m_mutexSendQueue.Unlock(); if (NULL == pEvent) continue; // Class must be a Level I class or a Level II // mirror class if (pEvent->vscp_class < 512) { frame.can_id = vscp_getCANALidFromVSCPevent(pEvent); frame.can_id |= CAN_EFF_FLAG; // Always extended if (0 != pEvent->sizeData) { frame.len = (pEvent->sizeData > 8 ? 8 : pEvent->sizeData); memcpy(frame.data, pEvent->pdata, frame.len); } } else if (pEvent->vscp_class < 1024) { pEvent->vscp_class -= 512; frame.can_id = vscp_getCANALidFromVSCPevent(pEvent); frame.can_id |= CAN_EFF_FLAG; // Always extended if (0 != pEvent->sizeData) { frame.len = ((pEvent->sizeData - 16) > 8 ? 8 : pEvent->sizeData - 16); memcpy(frame.data, pEvent->pdata + 16, frame.len); } } // Remove the event m_pObj->m_mutexSendQueue.Lock(); //m_pObj->m_sendQueue.DeleteNode(nodeClient); vscp_deleteVSCPevent(pEvent); m_pObj->m_mutexSendQueue.Unlock(); // Write the data int nbytes = write(sock, &frame, sizeof(struct can_frame)); } // event to send } // No data to read } // Inner loop // Close the socket close(sock); } // Outer loop return NULL; }