Как вернуть несколько необязательных переменных из функции в C / C ++? - PullRequest
0 голосов
/ 03 мая 2019

Я программирую ESP32 с модемом SIM7000 4G, и в библиотеке модемов есть функция, которая получает строку CSV с 21 переменной из модема и частично разбирает ее на переменные. Первоначальный автор заботился только о небольшом числе переменных и передавал указатели.

Если бы я хотел изменить код, чтобы все переменные были доступны , было бы неудобно пропустить 21 указатель, особенно если я могу заботиться только о нескольких переменных одновременно. Это случай для структуры? Какой самый удобный способ сделать данные доступными?

Функция отправляет команду AT на сотовый модем с чипом GPS (SIM7000). При получении команды микросхема внутренне анализирует данные NEMA из GPS и возвращает строку CSV со всеми соответствующими данными.

//FUNCTION FROM LIBRARY
 // get GPS information
  bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
    //String buffer = "";
    bool fix = false;

    sendAT(GF("+CGNSINF"));
    if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
      return false;
    }

    stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
    if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
    stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
    *lat =  stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
    *lon =  stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
    if (alt != NULL) *alt =  stream.readStringUntil(',').toFloat(); //altitude metere
    if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
    if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
    stream.readStringUntil(',');//Fix mode [0,1,2]
    stream.readStringUntil(',');//Reserved1
    stream.readStringUntil(',');//HDOP [0,99.9]
    stream.readStringUntil(',');//PDOP [0,99.9]
    stream.readStringUntil(',');//VDOP [0,99.9]
    stream.readStringUntil(',');//Reserved2
    if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
    if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
    stream.readStringUntil(',');//GLONASS Sats used
    stream.readStringUntil(',');//Reserved3
    stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
    stream.readStringUntil(',');//HPA (meters [0,9999.9])
    stream.readStringUntil(',');//VPA (meters [0,9999.9])
    stream.readStringUntil('\n');

    waitResponse();

    return fix;
}

//CALL FROM CODE
  gps_fixstatus = modem.getGPS(&gps_latitude, &gps_longitude, &gps_speed, &gps_altitude, &gps_course, &gps_view_satellites, &gps_used_satellites);
  if ( gps_fixstatus ) {
    gps_altitude=gps_altitude*3.2808; 
    sprintf(payload, "{\"lat\":%8f,\"long\":%8f,\"speed\":%2f,\"head\":%2f,\"alt\":%2f}", gps_latitude,gps_longitude, gps_speed, gps_course, gps_altitude); //JSON-ify
    SerialMon.println(payload); //JSON object
 }

Полный код: Библиотека - см. Строку 771 / Код вызова библиотеки - 134

Я разбудил библиотеку, чтобы она тоже возвращала информацию о курсе GPS, и подумал, почему бы не сделать все возвращенные данные доступными, но не кажется удобным для пользователя, что нужно пройти 21 указатель или определить 21 членную структуру и передать ее, если их основной код заботится только о широте / долготе, даже о скорости.

Одна библиотека, которую я люблю и использую с автономным приемником GPS, была TinyGPS ++ . Он возвращает данные как часть объекта, например, Serial.print(TinyGPSplus.location.lat()). Это лучший подход? Я изучал C / C ++ через Arduino, собирая разные примеры.

1 Ответ

1 голос
/ 14 мая 2019

Да. Это хороший пример для struct (ключевое слово c / c ++ для Structure (s)).

" Структуры, иногда называемые агрегатами, представляют собой наборы связанных переменных под одним именем. Структуры могут содержать переменные многих различных типов данных - в отличие от массивов, которые содержат только элементы одного типа данных."- C Как программировать 6. Под редакцией Пола и Харви Дейтеля.

В вашем случае вы должны вернуть около 21 различных переменных, верно? поэтому, используя структуру для создания пользовательского типа данных, допустим, что gpsData, членами которого являются 21 переменная, которую вы хотите вернуть, даст вам возможность написать функцию, которая возвращает данные с использованием «gpsData» в компактном виде. Конечно, вам нужно будет назначить каждый элемент производных / проанализированных данных из модуля gsm каждому члену «gpsData».

Ссылаясь на ваш код:

bool getGPS(float *lat, float *lon, float *speed=0, float *alt=0, float *course=0, int *vsat=0, int *usat=0) {
//String buffer = "";
bool fix = false;

sendAT(GF("+CGNSINF"));
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
  return false;
}

stream.readStringUntil(','); // mode [GNSS off=0, GNSS on=1]
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //utctime yyyyMMddhhmmss.sss
*lat =  stream.readStringUntil(',').toFloat(); //lat ±dd.dddddd
*lon =  stream.readStringUntil(',').toFloat(); //lon ±ddd.dddddd
if (alt != NULL) *alt =  stream.readStringUntil(',').toFloat(); //altitude metere
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed Km/hour [0,999.99]
if (course != NULL) *course = stream.readStringUntil(',').toFloat(); //course over ground degrees [0,360.00]
stream.readStringUntil(',');//Fix mode [0,1,2]
stream.readStringUntil(',');//Reserved1
stream.readStringUntil(',');//HDOP [0,99.9]
stream.readStringUntil(',');//PDOP [0,99.9]
stream.readStringUntil(',');//VDOP [0,99.9]
stream.readStringUntil(',');//Reserved2
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil(',');//GLONASS Sats used
stream.readStringUntil(',');//Reserved3
stream.readStringUntil(',');//C/N0 max (dBHz 0-55)
stream.readStringUntil(',');//HPA (meters [0,9999.9])
stream.readStringUntil(',');//VPA (meters [0,9999.9])
stream.readStringUntil('\n');

waitResponse();

return fix;

}

Эти переменные: float * lat, float * lon, float * speed = 0, float * alt = 0, float * course = 0, int * vsat = 0, int * usat = 0 могут быть помещены в структуру типа это:

struct gpsData{
    bool fix;
    float lat;
    float lon;
    float speed;
    float alt;
    float course;
    int vsat;
    int usat;
    ....x_datatype y_variable;
};

Где x_datatype y_variable ссылается на другие переменные-члены, которые вы можете добавить.

Ваша функция getGPS теперь будет выглядеть примерно так:

gpsData getGPS(){
     gsmData temp;
     temp.fix = false;
    // required processing...
    // ...

    return temp;
}

Когда вызывается getGPS (), как в следующем примере:

gpsData parsed_gps_data = getGPS();

Теперь вы можете получить интересующие вас параметры / элементы / атрибуты следующим образом:

parsed_gps_data.fix;
parsed_gps_data.lat;
parsed_gps_data.lon;

Надеюсь, это объяснение все прояснит.

...