⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmeap01.c

📁 GARMIN的GPS信息解释器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
Copyright (c) 2005, David M Howard (daveh at dmh2000.com)
All rights reserved.

This product is licensed for use and distribution under the BSD Open Source License.
see the file COPYING for more details.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

*/

/**
 * nmeap01.c
 * nmeap gps data parser
 * 
 * see the file COPYING for terms of the licnese
*/ 
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "nmeap.h"

/* this only works if you are sure you have an upper case hex digit */
#define HEXTOBIN(ch) ((ch <= '9') ? ch - '0' : ch - ('A' - 10))

/* forward references */
int nmeap_init(nmeap_context_t *context,void *user_data);
int nmeap_addParser(nmeap_context_t         *context,
					 const char             *sentence_name,
					 nmeap_sentence_parser_t sentence_parser,
					 nmeap_callout_t         sentence_callout,
                     void                  *sentence_data
					 );
int nmeap_tokenize(nmeap_context_t *context);
int nmeap_process(nmeap_context_t *context);
int nmeap_parse(nmeap_context_t *context,char ch);
int nmeap_parseBuffer(nmeap_context_t *context,const char *buffer,int *length);

/**
 * get a latitude out of a pair of nmea tokens 
 */
double nmeap_latitude(const char *plat,const char *phem)
{
    double lat;
    int    deg;
    double min;
    int    ns;
    
    assert(plat != 0);
    assert(phem != 0);
    
    if (*plat == 0) {
        return 0.0;
    }
    if (*phem == 0) {
        return 0.0;
    }
    
    /* north lat is +, south lat is - */
    if (*phem == 'N') {
        ns = 1;
    }
    else {
        ns = -1;
    }
    
    /* latitude is degrees, minutes, fractional minutes */
    /* no validation is performed on the token. it better be good.*/
    /* if it comes back 0.0 then probably the token was bad */
    lat = atof(plat);
    
    /* extract the degree part */
    deg = (int)(lat / 100.0);
    
    /* mask out the degrees */
    min = lat - (deg * 100.0);
    
    /* compute the actual latitude in degrees.decimal-degrees */
    lat = (deg + (min / 60.0)) * ns;
    
    return lat;
}

/**
 * get a longitude out of a pair of nmea tokens 
 */
double nmeap_longitude(const char *plon,const char *phem)
{
    double lon;
    int    deg;
    double min;
    int    ew;
    
    assert(plon != 0);
    assert(phem != 0);
    
    if (*plon == 0) {
        return 0.0;
    }
    if (*phem == 0) {
        return 0.0;
    }
    
    /* west long is negative, east long is positive */
    if (*phem == 'E') {
        ew = 1;
    }
    else {
        ew = -1;
    }
    
    /* longitude is degrees, minutes, fractional minutes */
    /* no validation is performed on the token. it better be good.*/
    /* if it comes back 0.0 then probably the token was bad */
    lon = atof(plon);
    
    /* extract the degree part */
    deg = (int)(lon / 100.0);
    
    /* mask out the degrees */
    min = lon - (deg * 100.0);
    
    /* compute the actual lonitude in degrees.decimal-degrees */
    lon = (deg + (min / 60.0)) * ew;

    
    return lon;
}

/**
 * get an altitude longitude out of a pair of nmea tokens
 * ALTITUDE is returned in METERS 
 */
double nmeap_altitude(const char *palt,const char *punits)
{
    double alt;
    
    if (*palt == 0) {
        return 0.0;
    }
    
    /* convert with no error checking */
    alt = atof(palt);
    
    if (*punits == 'M') {
        /* already in meters */ 
    }
    else if (*punits == 'F') {
        /* convert to feet */
        alt = alt * 3.2808399;
    }
    
    return alt;
}

/**
 * initialize an NMEA parser
 */
int nmeap_init(nmeap_context_t *context,void *user_data)
{
    assert(context != 0);

    memset(context,0,sizeof(*context));

    context->user_data = user_data;

    return 0;    
}

 
/**
 * register an NMEA sentence parser
 */
int nmeap_addParser(nmeap_context_t         *context,
					 const char             *sentence_name,
					 nmeap_sentence_parser_t sentence_parser,
					 nmeap_callout_t         sentence_callout,
                     void                  *sentence_data
					 )
{
    nmeap_sentence_t *s = 0;
    
    /* runtime error */
    assert(context != 0);
    
    /* sentence capacity overflow */
    if (context->sentence_count >= NMEAP_MAX_SENTENCES) {
        return -1;
    }
    
    /* point at next empty sentence buffer */
    s = &context->sentence[context->sentence_count];
    
    /* advance sentence data count */
    context->sentence_count++;
    
    /* clear the sentence data */
    memset(s,0,sizeof(*s));
    
    /* name */
    strncpy(s->name,sentence_name,NMEAP_MAX_SENTENCE_NAME_LENGTH);
    
    /* parser */
    s->parser = sentence_parser;
    
    /* callout */
    s->callout = sentence_callout;
    
    /* data */
    s->data    = sentence_data;

    return 0;
}

/** 
 * tokenize a buffer
 */
int nmeap_tokenize(nmeap_context_t *context)
{
    char *s;
    int   tokens;
    int   state;
    
    /* first token is header. assume it is there */
    tokens = 0;
    s = context->input;
    context->token[tokens] = s;
    
    /* get rest of tokens */
    tokens = 1;
    state = 0;
    while((*s != 0)&&(tokens < NMEAP_MAX_TOKENS)) {
        switch(state) {
        case 0:
            /* looking for end of a token */
            if (*s == ',') {
                /* delimit at the comma */
                *s    = 0;
                /* new token */
                state = 1;
            }
            break;
        case 1:
            /* start of next token, might be another comma */
            context->token[tokens++] = s;
            if (*s == ',') {
                /* delimit at the comma */
                *s    = 0;
            }
            else {   
                /* not a comma */
                state = 0;
            }
            break;
        default:
            state = 0;
            break;
        }
        
        // next character
        s++;
    }
    return tokens;
}

/**
 * process a sentence 
 */
int nmeap_process(nmeap_context_t *context)
{
    int id;
    int i;
    nmeap_sentence_t *s;
	
    /* copy the input to a debug buffer */
    /* remove debug_input when everything is working. */
    strncpy(context->debug_input,context->input,sizeof(context->debug_input));
    
    /* tokenize the input */
    context->tokens = nmeap_tokenize(context);
    
    /* try to find a matching sentence parser */
    /* this search is O(n). it has a lot of potential for optimization, at the expense of complexity, if you have a lot of sentences */
    /* binary search instead of linear (have to keep sentences in sorted order) O(NlogN) */
    /* OR, when sentences are added, create a TRIE structure to find the names with a constant time search O(5) */
    for(i=0;i<context->sentence_count;i++) {
        s = &context->sentence[i];
        assert(s != 0);
        if (strncmp(context->input_name,s->name,5) == 0) {
            /* found a match, call its parser */
            id = (*context->sentence[i].parser)(context,s);
            if (id > 0) {
                break;
            }
        }
    }
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -