Logga seriell kommunikation med filter?

Permalänk
Medlem

Logga seriell kommunikation med filter?

Hej, vet någon om det finns något litet smidigt program för att ta emot kommunikation via serieport och som kan logga till en fil baserat på filter?

Ska lägga på en splitter på en scannerbox så att infon kommer till både dit den ska och till en extra laptop som ska logga eventuella fel-scanningar.

T.ex. om en streckkod ser ut så här "12345A67890" vanligtvis, men ibland blir "12345Ax#%!!" dvs något blev fel vid scanning, så vill jag kunna logga den felaktiga strängen.

Alternativt funderar jag på att skriva ett eget program för det, men har ingen erfarenhet av serieportsprogrammering, får väl googla lite mer bara. Hjälper inte att jag försöker köra i Visual C++, när jag mest kört Amiga-programmering i E eller vanliga C förut X)

Skapa GUI går ju fort, men serieavläsning och filhantering har jag inte lyckats med än. Får leta mer som sagt, men finns det något bra loggerprogram så är det ju enklast.

Visa signatur

Shadows never sleep...
Specs: Ryzen 5600X, Powercolor Fighter RX 6700XT, ASUS B550-I ITX, 32GB 3600MHz DDR4, Bitfenix Phenom µ-ATX

Permalänk
Permalänk
Medlem

Inte direkt vad jag letade efter, men tack ändå.

Jag kör alltså på gammal seriell port, inte USB. Har dock hittat hur man konfigurerar och öppnar COM1 och skriver/läser från den. Nu brottas jag mest med Forms i Visual C++.

Funderar dock på att skippa ett fint "GUI" och bara göra ett kommandobaserat program som sparar loggfil, eftersom jag är osäker på var jag ska lägga all koden i grafiska projekt. Man kommer ju inte åt att ändra t.ex. Form1.Textbox1.Text ifrån main, eftersom det är själva Form1 som ligger och snurrar som en subrutin och resten av main inte exekveras förrän man stänger ner den.

Jag letar vidare, som sagt... I värsta fall får jag väl skriva ett Amiga-program och köra i UAE på laptopen X)

Visa signatur

Shadows never sleep...
Specs: Ryzen 5600X, Powercolor Fighter RX 6700XT, ASUS B550-I ITX, 32GB 3600MHz DDR4, Bitfenix Phenom µ-ATX

Permalänk
Hedersmedlem
Skrivet av blackeagle:

Funderar dock på att skippa ett fint "GUI" och bara göra ett kommandobaserat program som sparar loggfil, eftersom jag är osäker på var jag ska lägga all koden i grafiska projekt. Man kommer ju inte åt att ändra t.ex. Form1.Textbox1.Text ifrån main, eftersom det är själva Form1 som ligger och snurrar som en subrutin och resten av main inte exekveras förrän man stänger ner den.

Om du inte problem med att blanda användargränssnitt och funktionalitet kan du till exempel starta en tråd som hanterar inläsningen i Form1_Load() eller liknande. Eller lägga till en BackgroundWorker-komponent till formuläret.

Permalänk
Vila i frid
Skrivet av blackeagle:

Har dock hittat hur man konfigurerar och öppnar COM1 och skriver/läser från den.

Om det kan vara till någon hjälp så pysslade även jag med rs232 runt år 2k och hittade lite quirks man behöver göra i c++
<serial.h>

// Serial.h #ifndef __SERIAL_H__ #define __SERIAL_H__ #define FC_DTRDSR 0x01 #define FC_RTSCTS 0x02 #define FC_XONXOFF 0x04 #define ASCII_BEL 0x07 #define ASCII_BS 0x08 #define ASCII_LF 0x0A #define ASCII_CR 0x0D #define ASCII_XON 0x11 #define ASCII_XOFF 0x13 class CSerial { public: CSerial(int nPort = 2, int nBaud = 9600); ~CSerial(); BOOL Open(CTestMethod *Testshell); BOOL Close(); int ReadData( void *, int ); int SendData( const char *, int ); int ReadDataWaiting( void ); char* WaitUntil(char *SearchString,int Timeout = 60,BOOL PrintLines = TRUE); BOOL IsOpened( void ){ return( m_bOpened ); } protected: CTestMethod *TestShell; int Port,Baud; CString CompString; BOOL WriteCommByte( unsigned char ); HANDLE m_hIDComDev; OVERLAPPED m_OverlappedRead, m_OverlappedWrite; BOOL m_bOpened; }; #endif

Dold text

<serial.cpp>

// Serial.cpp #include "..\stdafx.h" #include "Serial.h" CSerial::CSerial(int nPort, int nBaud) { //Save port setting Port = nPort; Baud = nBaud; memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) ); memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) ); m_hIDComDev = NULL; m_bOpened = FALSE; } CSerial::~CSerial() { Close(); } BOOL CSerial::Open( CTestMethod *Testshell) { //Save test shell pointer TestShell = Testshell; if( m_bOpened ) return( TRUE ); char szPort[15]; char szComParams[50]; DCB dcb; wsprintf( szPort, "COM%d", Port ); m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL ); if( m_hIDComDev == NULL ) return( FALSE ); memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) ); memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) ); COMMTIMEOUTS CommTimeOuts; CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF; CommTimeOuts.ReadTotalTimeoutMultiplier = 0; CommTimeOuts.ReadTotalTimeoutConstant = 0; CommTimeOuts.WriteTotalTimeoutMultiplier = 0; CommTimeOuts.WriteTotalTimeoutConstant = 5000; SetCommTimeouts( m_hIDComDev, &CommTimeOuts ); wsprintf( szComParams, "COM%d:%d,n,8,1", Port, Baud ); m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); GetCommState( m_hIDComDev, &dcb ); dcb.BaudRate = Baud; dcb.Parity = 0; dcb.ByteSize = 8; dcb.fAbortOnError = 1; dcb.fRtsControl = 2; dcb.fTXContinueOnXoff = 1; dcb.fOutxCtsFlow = 1; unsigned char ucSet; ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 ); ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 ); ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 ); if( !SetCommState( m_hIDComDev, &dcb ) ||!SetupComm( m_hIDComDev, 10000, 10000 ) || m_OverlappedRead.hEvent == NULL ||m_OverlappedWrite.hEvent == NULL ) { DWORD dwError = GetLastError(); if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent ); if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent ); CloseHandle( m_hIDComDev ); return( FALSE ); } m_bOpened = TRUE; return( m_bOpened ); } BOOL CSerial::Close() { if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE ); if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent ); if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent ); CloseHandle( m_hIDComDev ); m_bOpened = FALSE; m_hIDComDev = NULL; return( TRUE ); } BOOL CSerial::WriteCommByte( unsigned char ucByte ) { BOOL bWriteStat; DWORD dwBytesWritten; bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite ); if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){ if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0; else{ GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE ); m_OverlappedWrite.Offset += dwBytesWritten; } } return( TRUE ); } int CSerial::SendData( const char *buffer, int size ) { if( !m_bOpened || m_hIDComDev == NULL ) return( 0 ); DWORD dwBytesWritten = 0; int i; for( i=0; i<size; i++ ){ WriteCommByte( buffer[i] ); dwBytesWritten++; } return( (int) dwBytesWritten ); } int CSerial::ReadDataWaiting( void ) { if( !m_bOpened || m_hIDComDev == NULL ) return( 0 ); DWORD dwErrorFlags; COMSTAT ComStat; ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat ); return( (int) ComStat.cbInQue ); } int CSerial::ReadData( void *buffer, int limit ) { if( !m_bOpened || m_hIDComDev == NULL ) return( 0 ); BOOL bReadStatus; DWORD dwBytesRead, dwErrorFlags; COMSTAT ComStat; ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat ); if( !ComStat.cbInQue ) return( 0 ); dwBytesRead = (DWORD) ComStat.cbInQue; if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit; bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead ); if( !bReadStatus ){ if( GetLastError() == ERROR_IO_PENDING ){ WaitForSingleObject( m_OverlappedRead.hEvent, 2000 ); return( (int) dwBytesRead ); } return( 0 ); } return( (int) dwBytesRead ); } //Waits until the search string is found or the time out is reached //Return a pointer to char string containing the recived answer //from RS232. char * CSerial::WaitUntil(char *SearchString,int Timeout,BOOL PrintLines) { CompString=""; int Length,Time=0,PrintLinePos=0,ReciveStringPos; char ReciveString[10000]; char PrintLine[1024]; Sleep(100); while(CompString.Find(SearchString)==-1) { //Check stop flag if(TestShell->GetStopFlag()) return NULL; Time=0; while(!ReadDataWaiting()) { if(Time==Timeout*20) { TestShell->TextOut("Time Out!!\\\nSearch string \"%s\" not found!",SearchString); return NULL; } if(TestShell->GetStopFlag()) return NULL; Sleep(50); Time++; } Length=ReadData(ReciveString,sizeof(ReciveString)); ReciveString[Length]='\0'; CompString=CompString+ReciveString; ReciveStringPos=0; while(ReciveString[ReciveStringPos]!='\0') { //Check stop flag if(TestShell->GetStopFlag()) return NULL; PrintLine[PrintLinePos]=ReciveString[ReciveStringPos]; PrintLinePos++; ReciveStringPos++; if(PrintLine[PrintLinePos-1]=='\n'||PrintLine[PrintLinePos-1]=='\r') { PrintLine[PrintLinePos]='\0'; if(PrintLines == TRUE) TestShell->TextOut("\\f1%s",PrintLine); PrintLinePos=0; } } } PrintLine[PrintLinePos]='\0'; if(PrintLines == TRUE) TestShell->TextOut("\\f1%s",PrintLine); return CompString.GetBuffer(1); }

Dold text

Exempelkod:

//****************************************************************************** int CCommunicationCheck::Measure(void) { const char * IPaddress,* Password; int ComPort,BaudRate; CString CompString; // do some stuff // GetData("IPaddress",&IPaddress); // GetData("Password",&Password); // GetData("ComPort",&ComPort); // GetData("BaudRate",&BaudRate); //******************************************************** // Check RS232 Communication //******************************************************** CSerial RNC_RS232(ComPort,BaudRate); if(RNC_RS232.Open(this)) TextOut("Serial connection established!"); else { TextOutError("Serial connection faild!"); BoxError("Serial connection faild!"," Communication test"); return TS_METHOD_ERROR; } //Connect RNC_RS232.SendData("\r\n",strlen("\r\n")); CompString = RNC_RS232.WaitUntil("$"); if(CompString.Find("$")==-1) { TextOutError("No prompt found!"); return TS_METHOD_ERROR; } else { TextOut("Prompt found!"); }

Dold text
Permalänk
Medlem

Alternativt om du har lust att ladda hem Visual Studio 2010 express så kan du modifiera och kompilera detta. Har det mest grundläggande men är inte provkört.

namespace SerialPortMonitor { using System; using System.IO; using System.IO.Ports; using System.Text.RegularExpressions; using System.Xml; public class Program { public static void Main ( string [ ] args ) { try { // todo: configure according to your scanner.. var port = new SerialPort ( "COM1", 9600, Parity.None, 8, StopBits.One ); // setup the event.. port.DataReceived += OnSerialportDataReceived; Console.WriteLine ( "Press any key to stop monitoring the serial port." ); Console.ReadKey ( ); } catch ( Exception ex ) { Console.WriteLine ( "Failed to open the serial port. {0} The application will stop.", ex.Message ); } } static void OnSerialportDataReceived ( object sender, SerialDataReceivedEventArgs e ) { try { var data = ( (SerialPort) sender ).ReadExisting ( ); // todo: replace the code below with you filter logic here.. // example: only allow alpha-numeric a-z & 0-9 if ( Regex.IsMatch (data, "^\\w*$") == false) { Console.WriteLine("Invalid characters was found in scanned data. The scanned string of '{0}' contains invalid characters.", data ); // todo: add you action here.. // example1: call an external process using data as an argument // example2: log it to file to file.. using ( TextWriter log = new StreamWriter("errors.log", true)) { // log the data with a xml encoding time like '2012-04-03T18:45:11.2308011+02:00'.. log.WriteLine ( "{0} - Invalid characters was found in scanned data. The scanned string of '{1}' contains invalid characters.", XmlConvert.ToString ( DateTime.Now, XmlDateTimeSerializationMode.Local ), data ); } } } catch ( Exception ex ) { Console.WriteLine ( "An error occured when reading from the serial port. {0}", ex.Message ); } } } }

tog bort onödig kodrad
Permalänk
Medlem

Tackar, jo jag kör redan Visual Studio Express 2010 på jobbet, så jag får testa imorgon igen.

Visa signatur

Shadows never sleep...
Specs: Ryzen 5600X, Powercolor Fighter RX 6700XT, ASUS B550-I ITX, 32GB 3600MHz DDR4, Bitfenix Phenom µ-ATX

Permalänk

Googlade lite och hittade detta: http://ttylog.sourceforge.net/

Borde nog fungera att utgå ifrån och sen kanske köra grep med någon fin regexp för att få fram det som önskas.

Visa signatur

"to conquer others is to have power, to conquer yourself is to know the way"