0

我正在使用 SIM7000 4G 调制解调器对 ESP32 进行编程,调制解调器库具有一个函数,该函数可以从调制解调器中获取包含 21 个变量的 CSV 字符串,并将其部分解析为变量。原作者只关心少数变量,因此传递了指针。

如果我想修改代码以使所有变量都可用,那么传递 21 个指针似乎很笨拙,尤其是当我一次只关心几个变量时。这是结构的情况吗?使数据可用的最用户友好的方式是什么?

该函数将AT 命令发送到带有 GPS 芯片的蜂窝调制解调器(SIM7000)。收到命令后,芯片会在内部解析来自 GPS 的 NEMA 数据,并返回包含所有相关数据的 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()). 这是最好的方法吗?我一直在通过 Arduino 学习 C/C++,将不同的示例混合在一起。

4

1 回答 1

1

是的。这对于结构(结构的 c/c++ 关键字)来说是一个很好的例子。

结构(有时称为聚合)是同一个名称下相关变量的集合。结构可能包含许多不同数据类型的变量,而数组只包含相同数据类型的元素。 ” - C 如何编程 6。由 Paul 和 Harvey Deitel 编着。

在您的情况下,您必须返回大约 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;

我希望这个解释能让一切都清楚。

于 2019-05-14T10:03:02.467 回答