Ok, dann hier der Quellcode:
class FmbSniffer: erstellt ein Objekt zur Kommunikation mit der Hardware, ein Thread zum Auslesen der Hardware und ein Thread zum Weitersenden der Daten:
Code: Alles auswählen
class FmbSniffer:public QObject
{
Q_OBJECT
public:
FmbSniffer();
~FmbSniffer();
SendThread *sendToView;
PollThread *pollFmbSniffer;
FTDI *ftdi;
signals:
void updateStatusTip(QString);
void ping();
public slots:
bool getDeviceStatus();
void pingSlot();
void sendFilterToDevice(QList<unsigned char>);
private:
QTimer *deviceStatusTimer;
QList<FmbData*> *telegramList;
QMutex *mutex;
};
Code: Alles auswählen
FmbSniffer::FmbSniffer()
{
telegramList = new QList<FmbData*>;
mutex = new QMutex;
// Erzeugen eines neuen FTDI-Objekts zur Kommunikation mit dem FTDI-Chip der Hardware
ftdi = new FTDI();
pollFmbSniffer = new PollThread(telegramList, mutex, ftdi);
pollFmbSniffer->start();
connect(pollFmbSniffer, SIGNAL(ping()), this, SLOT(pingSlot()));
sendToView = new SendThread(telegramList, mutex);
sendToView->start();
connect(sendToView, SIGNAL(ping()), this, SLOT(pingSlot()));
deviceStatusTimer = new QTimer();
deviceStatusTimer->setInterval(c_OPEN_CONNECTION_INTERVALL);
deviceStatusTimer->start();
connect(deviceStatusTimer, SIGNAL(timeout()), this, SLOT(getDeviceStatus()));
}
FmbSniffer::~FmbSniffer()
{
}
void FmbSniffer::pingSlot()
{
emit ping();
}
bool FmbSniffer::getDeviceStatus()
{
if (!ftdi->isInterfaceConnected())
{ // Wenn die Schnittstelle nicht geöffnet ist
// Schnittstelle öffnen
ftdi->Open();
if (ftdi->isInterfaceConnected() == true)
{ // Wenn die Schnittstelle erfolgreich geöffnet wurde
if (ftdi->isSnifferConnected() == true)
{ // wenn der Hitachi hinter der Schnittstelle gefunden wurde
emit updateStatusTip("FM-Sniffer verbunden");
return true;
}
else
{
emit updateStatusTip("USB-Schnittstelle geöffnet, FM-Sniffer nicht verbunden");
return false;
}
}
else
{ // Für den Fall, dass die Schnittstelle nicht geöffnet werden konnte
emit updateStatusTip("USB-Schnittstelle konnte nicht geöffnet werden");
return false;
}
}
else
{
if (pollFmbSniffer->nothingReceived > 150)
{ // Wenn 1,5 Sekunden lang nichts mehr empfangen wurde wird überprüft ob der Hitachi noch da ist
if (ftdi->isSnifferConnected() == true)
{ // wenn der Hitachi hinter der Schnittstelle gefunden wurde, true zurück geben
emit updateStatusTip("FM-Sniffer verbunden");
return true;
}
else
{ // der Hitachi antwortet nicht mehr...
emit updateStatusTip("USB-Schnittstelle geöffnet, FM-Sniffer nicht verbunden");
return false;
}
}
else
{ // Der Empfang der letzen Daten ist weniger als 1,5 Sekunden her
emit updateStatusTip("FM-Sniffer verbunden");
return true;
}
}
}
void FmbSniffer::sendFilterToDevice(QList<unsigned char> filterDaten)
{
// Erstellung eines Arrays auf dem Heap, dass die Listdaten enthalten wird
unsigned char* data= new unsigned char[filterDaten.count()];
// Füllen des Arrays mit den Daten aus der Liste
for (int i_liste = 0; i_liste < filterDaten.count(); i_liste++)
{
data[i_liste] = filterDaten.at(i_liste);
}
// Übergabe des Arrays an das Device-Objekt
ftdi->SendData(data, filterDaten.count());
delete data;
}
class PollThread liest von der Hardware und fügt die gelesenen Daten einer QList zu, die die gelesenen Daten puffern soll
Code: Alles auswählen
class PollThread:public QThread
{
Q_OBJECT
public:
PollThread(QList<FmbData*> *usedTelegramList, QMutex *usedMutex, Communication *communicationDevice);
~PollThread();
void start();
// Zeit seit dem letzen Empfang eines Bytes
unsigned int nothingReceived;
signals:
void ping();
void updateStatusTip(QString);
private slots:
void readFromHardware();
private:
void insertIntoNewTelegram(unsigned char, int);
Communication *device;
QList<unsigned char> receivedBytes;
QList<FmbData*> *telegramList;
//unsigned long i_list;
QTimer *pollTimer;
FmbData *newTelegram;
QMutex *mutex;
unsigned short i_receivedByte;
bool lastByteWasFF;
protected:
void run();
};
Code: Alles auswählen
PollThread::PollThread(QList<FmbData*> *usedTelegramList, QMutex *usedMutex, Communication *communicationDevice)
{
telegramList = usedTelegramList;
// Verwendung eines Mutex, um den Zugriff auf die Message-Liste zu verwalten
mutex = usedMutex;
device = communicationDevice;
receivedBytes.clear();
i_receivedByte = 0;
lastByteWasFF = false;
newTelegram = new FmbData;
pollTimer = new QTimer();
pollTimer->setInterval(c_POLL_INTERVALL);
pollTimer->start();
connect (pollTimer, SIGNAL(timeout()), this, SLOT(readFromHardware()));
nothingReceived = 0;
}
void PollThread::readFromHardware()
{
receivedBytes << (device->GetData());
// Nach den Telegramm-Ende-0xFF suchen
if (receivedBytes.lastIndexOf(0xFF) != -1)
{
newTelegram = new FmbData;
int i_receivedByte = 0;
for (int i_Liste = 0; i_Liste <= receivedBytes.lastIndexOf(0xFF); i_Liste++)
{
if ((receivedBytes.at(i_Liste) == 0xFF) and (i_Liste < receivedBytes.lastIndexOf(0xFF) and (receivedBytes.at(i_Liste + 1) == 0xFF)))
{
// Das 0xFF ist ein geschützes 0xFF im Datenstrom
// Byte überspringen
i_Liste++;
// nächstes Byte speichern
insertIntoNewTelegram(receivedBytes.at(i_Liste), i_receivedByte);
i_receivedByte++;
}
else if (receivedBytes.at(i_Liste) == 0xFF)
{
// Das 0xFF ist ein Telegramm-Ende-0xFF
mutex->lock();
telegramList->append(newTelegram);
mutex->unlock();
newTelegram = new FmbData;
i_receivedByte = 0;
}
else
{
// Normales Byte im Datenstrom sichern
insertIntoNewTelegram(receivedBytes.at(i_Liste), i_receivedByte);
i_receivedByte++;
}
}
delete newTelegram;
// Inhalt der Liste bis einschließlich des letzen Vorkommens von 0xFF löschen
while(receivedBytes.lastIndexOf(0xFF) != -1)
{
receivedBytes.removeFirst();
}
//emit updateStatusTip(QString::number(receivedBytes.size()));
if (receivedBytes.isEmpty())
{ // Speicher wieder freigeben, weil das nicht vom removeFirst() erledigt wird...
receivedBytes.clear();
}
// Zeit seit letzem Empfang auf Null setzten
nothingReceived = 0;
}
else
{ // Nichts empfangen, Zeit seit dem letzem Empfang erhöhen
nothingReceived++;
}
}
void PollThread::insertIntoNewTelegram(unsigned char byte, int i_receivedByte)
{
switch (i_receivedByte)
{
// Status-Byte
case 0:
newTelegram->Status.BYTE = byte;
break;
// Checksummen-Byte
case 1:
newTelegram->checksum = byte;
break;
// High-Byte der Länge
case 2:
newTelegram->laenge = (WORD) (byte << 8);
break;
// Low-Byte der Länge
case 3:
newTelegram->laenge |= (WORD) byte;
break;
// Stunden-Byte
case 4:
newTelegram->zeit.STUNDEN = byte;
break;
// Minuten-Byte
case 5:
newTelegram->zeit.MINUTEN = byte;
break;
// Sekunden-Byte
case 6:
newTelegram->zeit.SEKUNDEN = byte;
break;
case 7:
newTelegram->zeit.RESERVIERT = byte;
break;
// High-Byte der Millisekunden
case 8:
newTelegram->zeit.MILLISEKUNDEN = (WORD) (byte << 8);
break;
// Low-Byte der Millisekunden
case 9:
newTelegram->zeit.MILLISEKUNDEN |= (WORD) byte;
break;
// Teilnehmer-Byte der Nutzdaten
case 10:
newTelegram->FM_Data.Teilnehmer.BYTE = byte;
break;
// Funktions-Code der Nutzdaten
case 11:
newTelegram->FM_Data.FunktionsCode = byte;
break;
// restliche Nutzdatenbytes
default:
newTelegram->FM_Data.NUTZDATEN.append(byte);
break;
}
}
void PollThread::start()
{
run();
}
void PollThread::run()
{
}
PollThread::~PollThread()
{
}
class SendThread liest aus der gemeinsamen Liste der beiden Threads und sendet die Daten zu weiteren Verarbeitung weiter
Code: Alles auswählen
class SendThread : public QThread
{
Q_OBJECT
public:
SendThread(QList<FmbData*> *usedTelegramList, QMutex *usedMutex);
~SendThread();
void start();
signals:
void updateStatusTip(QString);
void newData(FmbData*);
void ping();
private slots:
void readData();
void sortData();
unsigned long timeToMillisekunden(FmbData*);
private:
QList<FmbData*> *telegramList;
FmbData *telegram;
QTimer *sendTimer;
QMutex *mutex;
protected:
void run();
};
Code: Alles auswählen
SendThread::SendThread(QList<FmbData*> *usedTelegramList, QMutex *usedMutex)
{
telegramList = usedTelegramList;
mutex = usedMutex;
sendTimer = new QTimer;
sendTimer->setInterval(c_SEND_NEW_DATA_INTERVALL);
sendTimer->start();
connect(sendTimer, SIGNAL(timeout()), this, SLOT (readData()));
}
void SendThread::start()
{
run();
}
void SendThread::run()
{
}
void SendThread::readData()
{
mutex->lock();
sortData();
while(telegramList->isEmpty() == false)
{
emit newData(telegramList->first());
delete telegramList->first();
telegramList->removeFirst();
}
mutex->unlock();
}
void SendThread::sortData()
{
bool getauscht;
FmbData* tempTelegram;
do
{
getauscht = false;
for (int i_liste = 0; i_liste < (telegramList->count() - 1); i_liste++)
{
if (timeToMillisekunden(telegramList->at(i_liste)) > timeToMillisekunden(telegramList->at(i_liste + 1)))
{
tempTelegram = telegramList->at(i_liste);
telegramList->removeAt(i_liste);
telegramList->insert(i_liste + 1, tempTelegram);
getauscht = true;
}
}
}while (getauscht);
}
unsigned long SendThread::timeToMillisekunden(FmbData *telegram)
{
return (unsigned long) telegram->zeit.MILLISEKUNDEN + telegram->zeit.SEKUNDEN * 1000 + telegram->zeit.MINUTEN * 1000 * 60 + telegram->zeit.MINUTEN * 1000 * 60 * 60;
}
SendThread::~SendThread()
{
}
Also im Endeffekt gibt es zwei QLists, die das Problem verursachen könnten:
die interne " QList<unsigned char> receivedBytes " von PollThread und die " QList<FmbData*> *telegramList " von FmbSniffer, die zum Datenaustauch zwischen den beiden Threads genutzt wird.