Merge pull request #165 from david-cermak/update/pick_update_prs

Accept some long standing example/demo PRs
This commit is contained in:
david-cermak
2022-11-03 11:05:01 +01:00
committed by GitHub
12 changed files with 717 additions and 22 deletions

View File

@ -29,10 +29,18 @@ menu "Example Configuration"
bool "BG96" bool "BG96"
help help
Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module. Quectel BG96 is a series of LTE Cat M1/Cat NB1/EGPRS module.
config EXAMPLE_MODEM_DEVICE_SIM7000
bool "SIM7000"
help
SIM7000 is a Multi-Band LTE-FDD and GSM/GPRS/EDGE module.
config EXAMPLE_MODEM_DEVICE_SIM7070
bool "SIM7070"
help
SIM7070 is Multi-Band CAT M and NB IoT module.
config EXAMPLE_MODEM_DEVICE_SIM7600 config EXAMPLE_MODEM_DEVICE_SIM7600
bool "SIM7600" bool "SIM7600"
help help
SIM7600 is Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module SIM7600 is a Multi-Band LTE-TDD/LTE-FDD/HSPA+ and GSM/GPRS/EDGE module.
endchoice endchoice
config EXAMPLE_MODEM_PPP_APN config EXAMPLE_MODEM_PPP_APN
@ -159,6 +167,21 @@ menu "Example Configuration"
default 1024 default 1024
help help
Buffer size of UART RX buffer. Buffer size of UART RX buffer.
choice EXAMPLE_FLOW_CONTROL
bool "Set preferred modem control flow"
default EXAMPLE_FLOW_CONTROL_NONE
help
Set the modem's preferred control flow
config EXAMPLE_FLOW_CONTROL_NONE
bool "No control flow"
config EXAMPLE_FLOW_CONTROL_SW
bool "SW control flow"
config EXAMPLE_FLOW_CONTROL_HW
bool "HW control flow"
endchoice
endmenu endmenu
endmenu endmenu

View File

@ -21,6 +21,15 @@
#include "esp_log.h" #include "esp_log.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE)
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE
#elif defined(CONFIG_EXAMPLE_FLOW_CONTROL_SW)
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_SW
#elif defined(CONFIG_EXAMPLE_FLOW_CONTROL_HW)
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_HW
#endif
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io" #define BROKER_URL "mqtt://mqtt.eclipseprojects.io"
static const char *TAG = "pppos_example"; static const char *TAG = "pppos_example";
@ -161,6 +170,7 @@ void app_main(void)
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN; dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN; dte_config.uart_config.rts_io_num = CONFIG_EXAMPLE_MODEM_UART_RTS_PIN;
dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN; dte_config.uart_config.cts_io_num = CONFIG_EXAMPLE_MODEM_UART_CTS_PIN;
dte_config.uart_config.flow_control = EXAMPLE_FLOW_CONTROL;
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE; dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE; dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE; dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
@ -174,6 +184,12 @@ void app_main(void)
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module..."); ESP_LOGI(TAG, "Initializing esp_modem for the SIM800 module...");
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, esp_netif); esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM800, &dte_config, &dce_config, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7000 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7000 module...");
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM7000, &dte_config, &dce_config, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7070 module...");
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM7070, &dte_config, &dce_config, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module..."); ESP_LOGI(TAG, "Initializing esp_modem for the SIM7600 module...");
esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM7600, &dte_config, &dce_config, esp_netif); esp_modem_dce_t *dce = esp_modem_new_dev(ESP_MODEM_DCE_SIM7600, &dte_config, &dce_config, esp_netif);
@ -181,6 +197,15 @@ void app_main(void)
ESP_LOGI(TAG, "Initializing esp_modem for a generic module..."); ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif); esp_modem_dce_t *dce = esp_modem_new(&dte_config, &dce_config, esp_netif);
#endif #endif
assert(dce);
if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
esp_err_t err = esp_modem_set_flow_control(dce, 2, 2); //2/2 means HW Flow Control.
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
return;
}
ESP_LOGI(TAG, "HW set_flow_control OK");
}
#elif defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB) #elif defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
while (1) { while (1) {
@ -189,13 +214,14 @@ void app_main(void)
const esp_modem_dte_config_t dte_usb_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config); const esp_modem_dte_config_t dte_usb_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config);
ESP_LOGI(TAG, "Waiting for USB device connection..."); ESP_LOGI(TAG, "Waiting for USB device connection...");
esp_modem_dce_t *dce = esp_modem_new_dev_usb(ESP_MODEM_DCE_BG96, &dte_usb_config, &dce_config, esp_netif); esp_modem_dce_t *dce = esp_modem_new_dev_usb(ESP_MODEM_DCE_BG96, &dte_usb_config, &dce_config, esp_netif);
assert(dce);
esp_modem_set_error_cb(dce, usb_terminal_error_handler); esp_modem_set_error_cb(dce, usb_terminal_error_handler);
vTaskDelay(pdMS_TO_TICKS(1000)); // Although the DTE should be ready after USB enumeration, sometimes it fails to respond without this delay vTaskDelay(pdMS_TO_TICKS(1000)); // Although the DTE should be ready after USB enumeration, sometimes it fails to respond without this delay
#else #else
#error Invalid serial connection to modem. #error Invalid serial connection to modem.
#endif #endif
assert(dce);
xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT); xEventGroupClearBits(event_group, CONNECT_BIT | GOT_DATA_BIT | USB_DISCONNECTED_BIT);
/* Run the modem demo app */ /* Run the modem demo app */
@ -214,7 +240,7 @@ void app_main(void)
int rssi, ber; int rssi, ber;
esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber); esp_err_t err = esp_modem_get_signal_quality(dce, &rssi, &ber);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d", err); ESP_LOGE(TAG, "esp_modem_get_signal_quality failed with %d %s", err, esp_err_to_name(err));
return; return;
} }
ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber); ESP_LOGI(TAG, "Signal quality: rssi=%d, ber=%d", rssi, ber);

View File

@ -0,0 +1,9 @@
idf_component_register(SRCS "SIM7070_gnss.cpp"
INCLUDE_DIRS "."
PRIV_REQUIRES esp_modem)
set_target_properties(${COMPONENT_LIB} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)

View File

@ -0,0 +1,341 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//
// Created on: 23.08.2022
// Author: franz
#include <string_view>
#include <charconv>
#include <list>
#include "sdkconfig.h"
#include "cxx_include/esp_modem_dte.hpp"
#include "cxx_include/esp_modem_dce.hpp"
#include "esp_modem_config.h"
#include "cxx_include/esp_modem_api.hpp"
#include "cxx_include/esp_modem_command_library_utils.hpp"
#include "esp_log.h"
#include "SIM7070_gnss.hpp"
constexpr auto const TAG = "SIM7070_gnss";
namespace gnss_factory {
using namespace esp_modem;
using namespace dce_factory;
class LocalFactory: public Factory {
using DCE_gnss_ret = std::unique_ptr<DCE_gnss>; // this custom Factory manufactures only unique_ptr<DCE>'s
public:
static DCE_gnss_ret create(const dce_config *config, std::shared_ptr<DTE> dte, esp_netif_t *netif)
{
return Factory::build_generic_DCE<SIM7070_gnss, DCE_gnss, DCE_gnss_ret>
(config, std::move(dte), netif);
}
};
} // namespace gnss_factory
/**
* @brief Helper create method which employs the DCE factory for creating DCE objects templated by a custom module
* @return unique pointer of the resultant DCE
*/
std::unique_ptr<DCE_gnss> create_SIM7070_GNSS_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif)
{
return gnss_factory::LocalFactory::create(config, std::move(dte), netif);
}
esp_modem::command_result get_gnss_information_sim70xx_lib(esp_modem::CommandableIf *t, esp_modem_gps_t &gps)
{
ESP_LOGV(TAG, "%s", __func__ );
std::string str_out;
auto ret = esp_modem::dce_commands::generic_get_string(t, "AT+CGNSINF\r", str_out);
if (ret != esp_modem::command_result::OK) {
return ret;
}
std::string_view out(str_out);
constexpr std::string_view pattern = "+CGNSINF: ";
if (out.find(pattern) == std::string_view::npos) {
return esp_modem::command_result::FAIL;
}
/**
* Parsing +CGNSINF:
* <GNSS run status>,
* <Fix status>,
* <UTC date & Time>,
* <Latitude>,
* <Longitude>,
* <MSL Altitude>,
* <Speed Over Ground>,
* <Course Over Ground>,
* <Fix Mode>,
* <Reserved1>,
* <HDOP>,
* <PDOP>,
* <VDOP>,
* <Reserved2>,
* <GNSS Satellites in View>,
* <Reserved3>,
* <HPA>,
* <VPA>
*/
out = out.substr(pattern.size());
int pos = 0;
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//GNSS run status
int GNSS_run_status;
if (std::from_chars(out.data(), out.data() + pos, GNSS_run_status).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
gps.run = (gps_run_t)GNSS_run_status;
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Fix status
{
std::string_view fix_status = out.substr(0, pos);
if (fix_status.length() > 1) {
int Fix_status;
if (std::from_chars(out.data(), out.data() + pos, Fix_status).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
gps.fix = (gps_fix_t)Fix_status;
} else {
gps.fix = GPS_FIX_INVALID;
}
} //clean up Fix status
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//UTC date & Time
{
std::string_view UTC_date_and_Time = out.substr(0, pos);
if (UTC_date_and_Time.length() > 1) {
if (std::from_chars(out.data() + 0, out.data() + 4, gps.date.year).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 4, out.data() + 6, gps.date.month).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 6, out.data() + 8, gps.date.day).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 8, out.data() + 10, gps.tim.hour).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 10, out.data() + 12, gps.tim.minute).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 12, out.data() + 14, gps.tim.second).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
if (std::from_chars(out.data() + 15, out.data() + 18, gps.tim.thousand).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
} else {
gps.date.year = 0;
gps.date.month = 0;
gps.date.day = 0;
gps.tim.hour = 0;
gps.tim.minute = 0;
gps.tim.second = 0;
gps.tim.thousand = 0;
}
} //clean up UTC date & Time
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Latitude
{
std::string_view Latitude = out.substr(0, pos);
if (Latitude.length() > 1) {
gps.latitude = std::stof(std::string(out.substr(0, pos)));
} else {
gps.latitude = 0;
}
} //clean up Latitude
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Longitude
{
std::string_view Longitude = out.substr(0, pos);
if (Longitude.length() > 1) {
gps.longitude = std::stof(std::string(out.substr(0, pos)));
} else {
gps.longitude = 0;
}
} //clean up Longitude
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Altitude
{
std::string_view Altitude = out.substr(0, pos);
if (Altitude.length() > 1) {
gps.altitude = std::stof(std::string(out.substr(0, pos)));
} else {
gps.altitude = 0;
}
} //clean up Altitude
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Speed Over Ground Km/hour
{
std::string_view gps_speed = out.substr(0, pos);
if (gps_speed.length() > 1) {
gps.speed = std::stof(std::string(gps_speed));
} else {
gps.speed = 0;
}
} //clean up gps_speed
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//Course Over Ground degrees
{
std::string_view gps_cog = out.substr(0, pos);
if (gps_cog.length() > 1) {
gps.cog = std::stof(std::string(gps_cog));
} else {
gps.cog = 0;
}
} //clean up gps_cog
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
// Fix Mode
{
std::string_view FixModesubstr = out.substr(0, pos);
if (FixModesubstr.length() > 1) {
int Fix_Mode;
if (std::from_chars(out.data(), out.data() + pos, Fix_Mode).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
gps.fix_mode = (gps_fix_mode_t)Fix_Mode;
} else {
gps.fix_mode = GPS_MODE_INVALID;
}
} //clean up Fix Mode
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//HDOP
{
std::string_view HDOP = out.substr(0, pos);
if (HDOP.length() > 1) {
gps.dop_h = std::stof(std::string(HDOP));
} else {
gps.dop_h = 0;
}
} //clean up HDOP
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//PDOP
{
std::string_view PDOP = out.substr(0, pos);
if (PDOP.length() > 1) {
gps.dop_p = std::stof(std::string(PDOP));
} else {
gps.dop_p = 0;
}
} //clean up PDOP
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//VDOP
{
std::string_view VDOP = out.substr(0, pos);
if (VDOP.length() > 1) {
gps.dop_v = std::stof(std::string(VDOP));
} else {
gps.dop_v = 0;
}
} //clean up VDOP
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//sats_in_view
{
std::string_view sats_in_view = out.substr(0, pos);
if (sats_in_view.length() > 1) {
if (std::from_chars(out.data(), out.data() + pos, gps.sats_in_view).ec == std::errc::invalid_argument) {
return esp_modem::command_result::FAIL;
}
} else {
gps.sats_in_view = 0;
}
} //clean up sats_in_view
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
out = out.substr(pos + 1);
if ((pos = out.find(',')) == std::string::npos) {
return esp_modem::command_result::FAIL;
}
//HPA
{
std::string_view HPA = out.substr(0, pos);
if (HPA.length() > 1) {
gps.hpa = std::stof(std::string(HPA));
} else {
gps.hpa = 0;
}
} //clean up HPA
out = out.substr(pos + 1);
//VPA
{
std::string_view VPA = out.substr(0, pos);
if (VPA.length() > 1) {
gps.vpa = std::stof(std::string(VPA));
} else {
gps.vpa = 0;
}
} //clean up VPA
return esp_modem::command_result::OK;
}
esp_modem::command_result SIM7070_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps)
{
return get_gnss_information_sim70xx_lib(dte.get(), gps);
}
esp_modem::command_result DCE_gnss::get_gnss_information_sim70xx(esp_modem_gps_t &gps)
{
return device->get_gnss_information_sim70xx(gps);
}

View File

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
//
// Created on: 23.08.2022
// Author: franz
#pragma once
#include "cxx_include/esp_modem_dce_factory.hpp"
#include "cxx_include/esp_modem_dce_module.hpp"
#include "nmea_parser.h"
/**
* @brief Definition of a custom SIM7070 class with GNSS capabilities.
* This inherits from the official esp-modem's SIM7070 device which contains all common library methods.
* On top of that, the SIM7070_gnss adds reading GNSS information, which is implemented in a private component.
*/
class SIM7070_gnss: public esp_modem::SIM7070 {
using SIM7070::SIM7070;
public:
esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps);
};
/**
* @brief DCE for the SIM7070_gnss. Here we've got to forward the general commands, aa well as the GNSS one.
*/
class DCE_gnss : public esp_modem::DCE_T<SIM7070_gnss> {
public:
using DCE_T<SIM7070_gnss>::DCE_T;
#define ESP_MODEM_DECLARE_DCE_COMMAND(name, return_type, num, ...) \
template <typename ...Agrs> \
esp_modem::return_type name(Agrs&&... args) \
{ \
return device->name(std::forward<Agrs>(args)...); \
}
DECLARE_ALL_COMMAND_APIS(forwards name(...)
{
device->name(...);
} )
#undef ESP_MODEM_DECLARE_DCE_COMMAND
esp_modem::command_result get_gnss_information_sim70xx(esp_modem_gps_t &gps);
};
/**
* @brief Helper create method which employs the customized DCE factory for building DCE_gnss objects
* @return unique pointer of the specific DCE
*/
std::unique_ptr<DCE_gnss> create_SIM7070_GNSS_dce(const esp_modem::dce_config *config,
std::shared_ptr<esp_modem::DTE> dte,
esp_netif_t *netif);

View File

@ -0,0 +1,133 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Origin: https://github.com/espressif/esp-idf/blob/master/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.h
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define GPS_MAX_SATELLITES_IN_USE (12)
#define GPS_MAX_SATELLITES_IN_VIEW (16)
/**
* @brief GPS fix type
*
*/
typedef enum {
GPS_FIX_INVALID, /*!< Not fixed */
GPS_FIX_GPS, /*!< GPS */
GPS_FIX_DGPS, /*!< Differential GPS */
} gps_fix_t;
/**
* @brief GPS run type
*
*/
typedef enum {
GPS_RUN_INVALID, /*!< Not fixed */
GPS_RUN_GPS, /*!< GPS */
} gps_run_t;
/**
* @brief GPS fix mode
*
*/
typedef enum {
GPS_MODE_INVALID, /*!< Not fixed */
GPS_MODE_2D, /*!< 2D GPS */
GPS_MODE_3D /*!< 3D GPS */
} gps_fix_mode_t;
/**
* @brief GPS satellite information
*
*/
typedef struct {
uint8_t num; /*!< Satellite number */
uint8_t elevation; /*!< Satellite elevation */
uint16_t azimuth; /*!< Satellite azimuth */
uint8_t snr; /*!< Satellite signal noise ratio */
} gps_satellite_t;
/**
* @brief GPS time
*
*/
typedef struct {
uint8_t hour; /*!< Hour */
uint8_t minute; /*!< Minute */
uint8_t second; /*!< Second */
uint16_t thousand; /*!< Thousand */
} gps_time_t;
/**
* @brief GPS date
*
*/
typedef struct {
uint8_t day; /*!< Day (start from 1) */
uint8_t month; /*!< Month (start from 1) */
uint16_t year; /*!< Year (start from 2000) */
} gps_date_t;
/**
* @brief NMEA Statement
*
*/
typedef enum {
STATEMENT_UNKNOWN = 0, /*!< Unknown statement */
STATEMENT_GGA, /*!< GGA */
STATEMENT_GSA, /*!< GSA */
STATEMENT_RMC, /*!< RMC */
STATEMENT_GSV, /*!< GSV */
STATEMENT_GLL, /*!< GLL */
STATEMENT_VTG /*!< VTG */
} nmea_statement_t;
/**
* @brief GPS object
*
*/
struct esp_modem_gps {
float latitude; /*!< Latitude (degrees) */
float longitude; /*!< Longitude (degrees) */
float altitude; /*!< Altitude (meters) */
gps_run_t run; /*!< run status */
gps_fix_t fix; /*!< Fix status */
uint8_t sats_in_use; /*!< Number of satellites in use */
gps_time_t tim; /*!< time in UTC */
gps_fix_mode_t fix_mode; /*!< Fix mode */
float dop_h; /*!< Horizontal dilution of precision */
float dop_p; /*!< Position dilution of precision */
float dop_v; /*!< Vertical dilution of precision */
uint8_t sats_in_view; /*!< Number of satellites in view */
gps_date_t date; /*!< Fix date */
float speed; /*!< Ground speed, unit: m/s */
float cog; /*!< Course over ground */
float hpa; /*!< Horizontal Position Accuracy */
float vpa; /*!< Vertical Position Accuracy */
};
typedef struct esp_modem_gps esp_modem_gps_t;
/**
* @brief NMEA Parser Event ID
*
*/
typedef enum {
GPS_UPDATE, /*!< GPS information has been updated */
GPS_UNKNOWN /*!< Unknown statements detected */
} nmea_event_id_t;
#ifdef __cplusplus
}
#endif

View File

@ -22,6 +22,10 @@ menu "Example Configuration"
bool "SIM7070" bool "SIM7070"
help help
SIM7070 is Multi-Band CAT M and NB IoT module. SIM7070 is Multi-Band CAT M and NB IoT module.
config EXAMPLE_MODEM_DEVICE_SIM7070_GNSS
bool "SIM7070_GNSS"
help
SIM7070 is Multi-Band CAT M and NB IoT module with Support for GNSS Location API
config EXAMPLE_MODEM_DEVICE_SIM7600 config EXAMPLE_MODEM_DEVICE_SIM7600
bool "SIM7600" bool "SIM7600"
help help
@ -119,4 +123,10 @@ menu "Example Configuration"
help help
Close the multiplexed mode at the end of the example and rollback to command mode. Close the multiplexed mode at the end of the example and rollback to command mode.
config BROKER_URI
string "Broker URL"
default "mqtt://test.mosquitto.org"
help
URL of an mqtt broker which this example connects to.
endmenu endmenu

View File

@ -25,6 +25,7 @@
#include "esp_vfs_dev.h" // For optional VFS support #include "esp_vfs_dev.h" // For optional VFS support
#include "esp_https_ota.h" // For potential OTA configuration #include "esp_https_ota.h" // For potential OTA configuration
#include "vfs_resource/vfs_create.hpp" #include "vfs_resource/vfs_create.hpp"
#include "SIM7070_gnss.hpp"
#if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE) #if defined(CONFIG_EXAMPLE_FLOW_CONTROL_NONE)
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE #define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_NONE
@ -34,7 +35,7 @@
#define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_HW #define EXAMPLE_FLOW_CONTROL ESP_MODEM_FLOW_CONTROL_HW
#endif #endif
#define BROKER_URL "mqtt://mqtt.eclipseprojects.io" #define BROKER_URL CONFIG_BROKER_URI
using namespace esp_modem; using namespace esp_modem;
@ -87,15 +88,17 @@ extern "C" void app_main(void)
assert(esp_netif); assert(esp_netif);
#if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1 #if CONFIG_EXAMPLE_MODEM_DEVICE_BG96 == 1
std::unique_ptr<DCE> dce = create_BG96_dce(&dce_config, dte, esp_netif); auto dce = create_BG96_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM800 == 1
std::unique_ptr<DCE> dce = create_SIM800_dce(&dce_config, dte, esp_netif); auto dce = create_SIM800_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7000 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7000 == 1
std::unique_ptr<DCE> dce = create_SIM7000_dce(&dce_config, dte, esp_netif); auto dce = create_SIM7000_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070 == 1
std::unique_ptr<DCE> dce = create_SIM7070_dce(&dce_config, dte, esp_netif); auto dce = create_SIM7070_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070_GNSS == 1
auto dce = create_SIM7070_GNSS_dce(&dce_config, dte, esp_netif);
#elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1 #elif CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600 == 1
std::unique_ptr<DCE> dce = create_SIM7600_dce(&dce_config, dte, esp_netif); auto dce = create_SIM7600_dce(&dce_config, dte, esp_netif);
#else #else
#error "Unsupported device" #error "Unsupported device"
#endif #endif
@ -135,6 +138,12 @@ extern "C" void app_main(void)
} }
std::cout << "Operator name:" << str << std::endl; std::cout << "Operator name:" << str << std::endl;
#if CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070_GNSS == 1
if (dce->set_gnss_power_mode(1) == esp_modem::command_result::OK) {
std::cout << "Modem set_gnss_power_mode: OK" << std::endl;
}
#endif
/* Try to connect to the network and publish an mqtt topic */ /* Try to connect to the network and publish an mqtt topic */
ESPEventHandlerSync event_handler(loop); ESPEventHandlerSync event_handler(loop);
event_handler.listen_to(ESPEvent(IP_EVENT, ESPEventID(ESP_EVENT_ANY_ID))); event_handler.listen_to(ESPEvent(IP_EVENT, ESPEventID(ESP_EVENT_ANY_ID)));
@ -184,6 +193,43 @@ extern "C" void app_main(void)
std::cout << "Modem IMSI number:" << str << std::endl; std::cout << "Modem IMSI number:" << str << std::endl;
} }
#if CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070_GNSS == 1
esp_modem_gps_t gps;
for (int i = 0; i < 200; ++i) {
if (dce->get_gnss_information_sim70xx(gps) == esp_modem::command_result::OK) {
ESP_LOGI(TAG, "gps.run %i",
gps.run);
ESP_LOGI(TAG, "gps.fix %i",
gps.fix);
ESP_LOGI(TAG, "gps.date.year %i gps.date.month %i gps.date.day %i",
gps.date.year, gps.date.month, gps.date.day);
ESP_LOGI(TAG, "gps.tim.hour %i gps.tim.minute %i gps.tim.second %i gps.tim.thousand %i",
gps.tim.hour, gps.tim.minute, gps.tim.second, gps.tim.thousand);
ESP_LOGI(TAG, "gps.latitude %f gps.longitude %f ",
gps.latitude, gps.longitude );
ESP_LOGI(TAG, "gps.altitude %f",
gps.altitude);
ESP_LOGI(TAG, "gps.speed %f",
gps.speed);
ESP_LOGI(TAG, "gps.cog %f",
gps.cog);
ESP_LOGI(TAG, "gps.fix_mode %i",
gps.fix_mode);
ESP_LOGI(TAG, "gps.dop_h %f gps.dop_p %f gps.dop_v %f ",
gps.dop_h, gps.dop_p, gps.dop_v );
ESP_LOGI(TAG, "gps.sats_in_view %i",
gps.sats_in_view);
ESP_LOGI(TAG, "gps.hpa %f gps.vpa %f",
gps.hpa, gps.vpa);
}
vTaskDelay(pdMS_TO_TICKS(1000)); //Wait
}
#endif // CONFIG_EXAMPLE_MODEM_DEVICE_SIM7070_GNSS
#if CONFIG_EXAMPLE_PERFORM_OTA == 1 #if CONFIG_EXAMPLE_PERFORM_OTA == 1
esp_http_client_config_t config = { }; esp_http_client_config_t config = { };
config.skip_cert_common_name_check = true; config.skip_cert_common_name_check = true;

View File

@ -9,4 +9,4 @@ CONFIG_PARTITION_TABLE_TWO_OTA=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=y CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=y
CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=y CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=y
CONFIG_MAIN_TASK_STACK_SIZE=8192 CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

View File

@ -1,4 +1,4 @@
version: "0.1.24" version: "0.1.25"
description: esp modem description: esp modem
url: https://github.com/espressif/esp-protocols/tree/master/components/esp_modem url: https://github.com/espressif/esp-protocols/tree/master/components/esp_modem
dependencies: dependencies:

View File

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
namespace esp_modem::dce_commands {
/**
* @brief Generic command that passes on supplied pass_phrase, and fails on fail_phrase
* @param t Any "Command-able" class that implements "command()" method
* @param command Command to issue
* @param pass_phrase Pattern to find in replies to complete the command successfully
* @param fail_phrase If this pattern found the command fails immediately
* @param timeout_ms Command timeout in ms
* @return Generic command return type (OK, FAIL, TIMEOUT)
*/
command_result generic_command(CommandableIf *t, const std::string &command,
const std::string &pass_phrase,
const std::string &fail_phrase, uint32_t timeout_ms);
/**
* @brief Utility command to send command and return reply (after DCE says OK)
* @param t Anything that is "command-able"
* @param command Command to issue
* @param output String to return
* @param timeout_ms
* @param timeout_ms Command timeout in ms
* @return Generic command return type (OK, FAIL, TIMEOUT)
*/
command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms = 500);
/**
* @brief Generic command that passes on "OK" and fails on "ERROR"
* @param t Anything that is "command-able"
* @param command Command to issue
* @param timeout
* @param timeout_ms Command timeout in ms
* @return Generic command return type (OK, FAIL, TIMEOUT)
*/
command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout_ms = 500);
} // esp_modem::dce_commands

View File

@ -10,15 +10,16 @@
#include "cxx_include/esp_modem_dte.hpp" #include "cxx_include/esp_modem_dte.hpp"
#include "cxx_include/esp_modem_dce_module.hpp" #include "cxx_include/esp_modem_dce_module.hpp"
#include "cxx_include/esp_modem_command_library.hpp" #include "cxx_include/esp_modem_command_library.hpp"
#include "cxx_include/esp_modem_command_library_utils.hpp"
namespace esp_modem::dce_commands { namespace esp_modem::dce_commands {
static const char *TAG = "command_lib"; static const char *TAG = "command_lib";
command_result generic_command(CommandableIf *t, const std::string &command, static command_result generic_command(CommandableIf *t, const std::string &command,
const std::list<std::string_view> &pass_phrase, const std::list<std::string_view> &pass_phrase,
const std::list<std::string_view> &fail_phrase, const std::list<std::string_view> &fail_phrase,
uint32_t timeout_ms) uint32_t timeout_ms)
{ {
ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str()); ESP_LOGD(TAG, "%s command %s\n", __func__, command.c_str());
return t->command(command, [&](uint8_t *data, size_t len) { return t->command(command, [&](uint8_t *data, size_t len) {
@ -40,9 +41,9 @@ command_result generic_command(CommandableIf *t, const std::string &command,
} }
static inline command_result generic_command(CommandableIf *t, const std::string &command, command_result generic_command(CommandableIf *t, const std::string &command,
const std::string &pass_phrase, const std::string &pass_phrase,
const std::string &fail_phrase, uint32_t timeout_ms) const std::string &fail_phrase, uint32_t timeout_ms)
{ {
ESP_LOGV(TAG, "%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
const auto pass = std::list<std::string_view>({pass_phrase}); const auto pass = std::list<std::string_view>({pass_phrase});
@ -50,7 +51,7 @@ static inline command_result generic_command(CommandableIf *t, const std::string
return generic_command(t, command, pass, fail, timeout_ms); return generic_command(t, command, pass, fail, timeout_ms);
} }
static inline command_result generic_get_string(CommandableIf *t, const std::string &command, std::string_view &output, uint32_t timeout_ms = 500) static command_result generic_get_string(CommandableIf *t, const std::string &command, std::string_view &output, uint32_t timeout_ms = 500)
{ {
ESP_LOGV(TAG, "%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return t->command(command, [&](uint8_t *data, size_t len) { return t->command(command, [&](uint8_t *data, size_t len) {
@ -77,7 +78,7 @@ static inline command_result generic_get_string(CommandableIf *t, const std::str
}, timeout_ms); }, timeout_ms);
} }
static inline command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms = 500) command_result generic_get_string(CommandableIf *t, const std::string &command, std::string &output, uint32_t timeout_ms)
{ {
ESP_LOGV(TAG, "%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
std::string_view out; std::string_view out;
@ -89,10 +90,10 @@ static inline command_result generic_get_string(CommandableIf *t, const std::str
} }
static inline command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout = 500) command_result generic_command_common(CommandableIf *t, const std::string &command, uint32_t timeout_ms)
{ {
ESP_LOGV(TAG, "%s", __func__ ); ESP_LOGV(TAG, "%s", __func__ );
return generic_command(t, command, "OK", "ERROR", timeout); return generic_command(t, command, "OK", "ERROR", timeout_ms);
} }
command_result sync(CommandableIf *t) command_result sync(CommandableIf *t)