Ejemplo n.º 1
0
void NmeaParser::parse(char letter) {
    bool commit = false; // flag to commit collected sentence
    bool clear = false; // flag to clear collected sentence

    // check for starting symbol
    bool isStart = false;
    if (letter == '$') {
        isStart = true;
        if (state != S_SOS) {
#ifdef GLOBPOS_PRINT_ERRORS
            fprintf(stderr, "Unexpected start of sentence at state %d\n", state);
#endif
            state = S_SOS;
            commit = true; // maybe there was something valid
        }
    }

    // check for ending symbol
    if (letter == END[currentEnd]) {
        currentEnd++;
    } else {
        currentEnd = 0;

        // can be only \n or any wrong char
        if (letter == END[1] || !isprint(letter)) {
            currentEnd = 2;
        }
    }
    bool isEnd = currentEnd > 0;

    bool isSentence = false; // is it a meaningful character of the sentence
    bool startData = false; // start new current data part

    switch (state) {
        case S_SOS:
            if (isStart) {
                state = S_ADDRESS;
                clear = true;
            } else {
#ifdef GLOBPOS_PRINT_ERRORS
                fprintf(stderr, "Wrong starting character %d\n", (int)letter);
#endif
            }
            break;
        case S_ADDRESS:
            if (letter == ',') {
                state = S_DATA;
                startData = true;
            } else {
                addressLength++;
            }
            isSentence = true;
            break;
        case S_DATA:
            if (letter == ',') {
                data.add(currentData);
                startData = true;
                isSentence = true;
            } else if (letter == '*') {
                data.add(currentData);
                state = S_CHECKSUM;
            } else if (isEnd) {
                data.add(currentData);
                state = S_END;
            } else {
                currentData.size++;
                isSentence = true;
            }
            break;
        case S_CHECKSUM:
            if (isEnd) {
                state = S_END;
            } else {
                checksum.add(letter);
            }
            if (checksum.length == CHECKSUM_LENGTH) {
                state = S_END;
            }
            break;
        case S_END:
            if (!isEnd) {
#ifdef GLOBPOS_PRINT_ERRORS
                fprintf(stderr, "Wrong ending character %d\n", (int)letter);
#endif
            }
            break;
        default:
            fprintf(stderr, "Unknown state %d\n", state);
            break;
    }

    if (isSentence) {
        if (sentence.length >= MAX_SENTENCE_LENGTH) {
            fprintf(stderr, "Length limit reached\n");
        }
        sentence.add(letter);
    }

    if (startData) {
        currentData.offset = sentence.length; // should be next character after comma
        currentData.size = 0;
    }

    if (isEnd) {
        if (state != S_END) {
#ifdef GLOBPOS_PRINT_ERRORS
            fprintf(stderr, "Unexpected end of sentence at state %d\n", state);
#endif
        }

        if (currentEnd == sizeof(END)) {
            currentEnd = 0;

            commit = true;
            state = S_SOS;
        }
    }

    if (commit) {
        if (addressLength > 0 && data.length > 0) {
            if (verifyChecksum) {
                if (verifyCurrentSentence()) {
                    commitCurrentSentence();
                } else {
                    std::string addressStr(sentence.content, addressLength);
                    std::string checksumStr(checksum.content, checksum.length);
                    fprintf(stderr, "Checksum %s verification failed for %s with %d fields\n",
                            checksumStr.c_str(), addressStr.c_str(), (int)data.length);
                }
            } else {
                commitCurrentSentence();
            }
        }
        clear = true;
    }

    if (clear) {
        clearCurrentSentence();
    }
}
Ejemplo n.º 2
0
                void GPRMC::decode() {
                    //$GPRMC,162748,A,5214.0456,N,01103.4540,E,0.0,0.0,250309,0.0,E,A*17CRLF
                    if (m_message.size() > 65) {
                        uint32_t pos = 0;
                        string strGPRMC = m_message.substr(pos, 6);

                        if (strGPRMC != "$GPRMC") {
                            clog << "No $GPRMC message." << endl;
                            return;
                        }

                        ////////////////////////////////////////////////////////

                        pos = pos + 6 + 1; // Consume value + ","
                        stringstream timeStr(m_message.substr(pos, 6));
                        uint32_t time;
                        timeStr >> time;

                        pos = pos + 6 + 1; // Consume value + ","
                        char type = m_message.at(pos);
                        if (type != 'A') {
                            clog << "No data message." << endl;
                            return;
                        }

                        ////////////////////////////////////////////////////////

                        pos = pos + 1 + 1; // Consume value + ","
                        stringstream latitudeStr(m_message.substr(pos, 2));

                        pos = pos + 2; // Consume value

                        stringstream latitudeArcMinuteStr(m_message.substr(pos, 7));

                        double temp;
                        double latitude = 0;
                        latitudeStr >> temp;
                        latitude = temp;
                        latitudeArcMinuteStr >> temp;
                        latitude += (temp / 60);

                        pos = pos + 7 + 1; // Consume value + ","
                        char LAT = m_message.at(pos);

                        m_coordinate.setLatitude(latitude);
                        m_coordinate.setLATITUDE((LAT == 'N') ? WGS84Coordinate::NORTH : WGS84Coordinate::SOUTH);

                        ////////////////////////////////////////////////////////

                        pos = pos + 1 + 1; // Consume value + ","

                        stringstream longitudeStr(m_message.substr(pos, 3));

                        pos = pos + 3; // Consume value

                        stringstream longitudeArcMinuteStr(m_message.substr(pos, 7));

                        double longitude = 0;
                        longitudeStr >> temp;
                        longitude = temp;
                        longitudeArcMinuteStr >> temp;
                        longitude += (temp / 60);

                        pos = pos + 7 + 1; // Consume value + ","
                        char LON = m_message.at(pos);

                        m_coordinate.setLongitude(longitude);
                        m_coordinate.setLONGITUDE((LON == 'W') ? WGS84Coordinate::WEST: WGS84Coordinate::EAST);

                        ////////////////////////////////////////////////////////

                        pos = pos + 1 + 1; // Consume value + ","

                        stringstream velocityStr;
                        char c = m_message.at(pos);
                        while (c != ',') {
                            velocityStr << c;
                            pos++;
                            c = m_message.at(pos);
                        }

                        pos = pos + 1; // Consume ","

                        stringstream directionStr;
                        c = m_message.at(pos);
                        while (c != ',') {
                            directionStr << c;
                            pos++;
                            c = m_message.at(pos);
                        }

                        pos = pos + 1; // Consume ","

                        stringstream ddmmStr(m_message.substr(pos, 4));

                        pos = pos + 4; // Consume value

                        stringstream yyStr(m_message.substr(pos, 2));
                        uint32_t yy;
                        yyStr >> yy;

                        stringstream dateTimeStr;
                        dateTimeStr << ddmmStr.str() << GPRMC::BASE_YEAR + yy << timeStr.str();
                        m_timeStamp = TimeStamp(dateTimeStr.str());

                        pos = pos + 2 + 1; // Consume value + ","

                        stringstream magneticDeviationStr;
                        c = m_message.at(pos);
                        while (c != ',') {
                            magneticDeviationStr << c;
                            pos++;
                            c = m_message.at(pos);
                        }

                        pos = pos + 1; // Consume ","

                        LON = m_message.at(pos);

                        pos = pos + 1 + 1; // Consume value + ","
                        type = m_message.at(pos);

                        pos = pos + 1 + 1; // Consume value + "*"
                        const uint32_t messageEnd = pos;

                        stringstream checksumStr(m_message.substr(pos));
                        uint32_t checksum;
                        checksumStr >> hex >> checksum;

                        uint32_t XOR = 0;
                        for(uint32_t i = 0; i < messageEnd; i++) {
                            XOR ^= m_message.at(i);
                        }

                        if (XOR != checksum) {
                            clog << "GPRMC corrupt!" << endl;
                        }
                    }