Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BG95 Support (IDFGH-14480) #739

Open
michaelboeding opened this issue Jan 22, 2025 · 8 comments
Open

BG95 Support (IDFGH-14480) #739

michaelboeding opened this issue Jan 22, 2025 · 8 comments
Assignees
Labels
Status: Opened Issue is new Type: Feature Request Feature Request for esp-protocols

Comments

@michaelboeding
Copy link

Is your feature request related to a problem?

I see there is B96 support could we have the BG95 added also? Thanks

Describe the solution you'd like.

No response

Describe alternatives you've considered.

No response

Additional context.

No response

@michaelboeding michaelboeding added the Type: Feature Request Feature Request for esp-protocols label Jan 22, 2025
@github-actions github-actions bot changed the title BG95 Support BG95 Support (IDFGH-14480) Jan 22, 2025
@espressif-bot espressif-bot added the Status: Opened Issue is new label Jan 22, 2025
@michaelboeding
Copy link
Author

This would actually not just be for the BG95 but would support all of the cellular modules that fall under the MDM9205 chipset. This would be very useful. Or if there is a very detailed guide to implementing a custom cellular modem I could do this myself.

Image

@david-cermak
Copy link
Collaborator

Hi @michaelboeding

Have you tested the BG95 with the modem library, initialized as a "GENERIC DEVICE"? I briefly checked the spec and think it should work as is, the BG95 is a drop in replacement for BG96 and is IMO even "closer" to the generic device than the bg96 (just some specific commands like reset or TCP socket API might be different)

@michaelboeding
Copy link
Author

Hey @david-cermak, haven't tried that but will tonight and report back. Thanks!

@michaelboeding
Copy link
Author

I was able to get a data connection going in CMUX mode it seems using the generic module! Thanks for that!

I BG95: UART DTE created successfully
I BG95: Generic DCE created successfully
E BG95: Failed to set flow control
I BG95: CMUX mode set successfully
I BG95: Sync OK
I BG95: IMSI: [REDACTED]
I BG95: IMEI: [REDACTED]
I BG95: Module name: BG95-M3
I BG95: Firmware version: BG95M3LAR02A03
I BG95: ICCID: [REDACTED]
I BG95: Manufacturer: Quectel
I BG95: Model: BG95-M3
I BG95: Signal quality: RSSI=99, BER=99
I BG95: Connecting to cellular network this could take up to 240 seconds
I esp-netif_lwip-ppp: Connection lost
I BG95: IP event received
I BG95: Event ID: 7
I BG95: Modem Disconnect from PPP Server
I BG95: Attempting to recover connection...

One weird thing I am seeing though is that sometimes if I had a connection previously or power cycle etc the device will almost immediately just say disconnected and send me a disconnect ppp event. Any ideas on this @david-cermak

@michaelboeding
Copy link
Author

michaelboeding commented Feb 9, 2025

Ok I have made more progress on this. It seems like I have now setup CMUX correctly and set the URC handler so that I get the URCs after entering CMUX mode.

But I still have this weird ppp issue....basically what I'm trying to accomplish is the following.

  1. Setup the Module in CMUX mode
  2. Setup the AT commands to inform me via URCs of the changes in network status as events.
  3. Once I get the +CREG (or any other related network status URC) I want to then make sure the networks interface for ppp is up but I can't seem to get this to work?
  4. I would like to handle changes in network status from the URC to pause/start/resume the network interface.
  5. I will also want to be sending the message to get the GNSS data from the BG95 but I do think I have that figured out unless there is need for another virtual terminal for that in CMUX mode? I would assume you could just do this over the command terminal?

Do I need to be handling the multiple terminals myself? I'm a little lost at this point and haven't been able to find any example that shows exactly what I want here unless I'm misunderstanding something? Any help would be greatly appreciated. @david-cermak . Also important to note that if my module gets its network up and then I restart the program it will work for connecting to PPP.

@michaelboeding
Copy link
Author

Heres my current code also if this is helpful

static const char *TAG = "BG95";

void BG95::on_ppp_changed(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
    ESP_LOGI(TAG, "PPP changed event");
    BG95* bg95 = static_cast<BG95*>(arg);
    if (event_id == NETIF_PPP_ERRORUSER) {
        if (bg95->callbacks) {
            bg95->callbacks->cellularErrorOccured(bg95);
        }
        xEventGroupSetBits(bg95->event_group, ERROR_BIT);
    }
}

void BG95::on_ip_event(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
    BG95* bg95 = static_cast<BG95*>(arg);
    
    ESP_LOGI(TAG, "IP event recieved");
    ESP_LOGI(TAG, "Event ID: %d", event_id);
    if (event_id == IP_EVENT_PPP_GOT_IP) {
        esp_netif_dns_info_t dns_info;

        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        esp_netif_t *netif = event->esp_netif;

        ESP_LOGI(TAG, "Modem Connect to PPP Server");
        ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
        ESP_LOGI(TAG, "IP          : " IPSTR, IP2STR(&event->ip_info.ip));
        ESP_LOGI(TAG, "Netmask     : " IPSTR, IP2STR(&event->ip_info.netmask));
        ESP_LOGI(TAG, "Gateway     : " IPSTR, IP2STR(&event->ip_info.gw));
        esp_netif_get_dns_info(netif, ESP_NETIF_DNS_MAIN, &dns_info);
        ESP_LOGI(TAG, "Name Server1: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
        esp_netif_get_dns_info(netif, ESP_NETIF_DNS_BACKUP, &dns_info);
        ESP_LOGI(TAG, "Name Server2: " IPSTR, IP2STR(&dns_info.ip.u_addr.ip4));
        ESP_LOGI(TAG, "~~~~~~~~~~~~~~");
        xEventGroupSetBits(bg95->event_group, CONNECT_BIT);
        if (bg95->callbacks) {
            bg95->callbacks->cellularNetworkConnected(bg95);
        }

    } else if (event_id == IP_EVENT_PPP_LOST_IP) {
        ESP_LOGI(TAG, "Modem Disconnect from PPP Server");
       // xEventGroupSetBits(bg95->event_group, DISCONNECT_BIT);
       //try to recover the connection
       ESP_LOGI(TAG, "Attempting to recover connection...");
       
        if (bg95->callbacks) {
            bg95->callbacks->cellularNetworkDisconnected(bg95);
        }
        
    } else if (event_id == IP_EVENT_GOT_IP6) {
        ESP_LOGI(TAG, "GOT IPv6 event!");
        ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data;
        ESP_LOGI(TAG, "Got IPv6 address " IPV6STR, IPV62STR(event->ip6_info.ip));
    }
}

//read callback
bool BG95::read_callback(uint8_t *data, size_t len){
    ESP_LOGI(TAG, "Read callback called");
    //log the data
    ESP_LOGI(TAG, "Read data: %s", data);


    return true;
}




BG95::BG95() {
    ESP_LOGI(TAG, "Constructor called");
    // Initialize event group
    event_group = xEventGroupCreate();

    // Power up first before any other initialization
    gpio_config_t power_up_pin_config = {
        .pin_bit_mask = (1ULL << BG95_PWK_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&power_up_pin_config);
    powerUp();
    ESP_LOGI(TAG, "BG95 finished power up sequence");
    vTaskDelay(pdMS_TO_TICKS(2000)); // Give module time to stabilize

    // Initialize ESP-NETIF after power up
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    
    /* Configure the PPP netif */
    esp_modem_dce_config dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG("soracom.io");
    esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
    esp_netif = esp_netif_new(&netif_ppp_config);
    assert(esp_netif);

    // Configure the DTE
    esp_modem_dte_config dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
    dte_config.uart_config.port_num = UART_NUM_1;
    dte_config.uart_config.tx_io_num = BG95_TX_PIN;
    dte_config.uart_config.rx_io_num = BG95_RX_PIN;
    dte_config.uart_config.rts_io_num = BG95_RTS_PIN;
    dte_config.uart_config.cts_io_num = BG95_CTS_PIN;
    dte_config.uart_config.flow_control = ESP_MODEM_FLOW_CONTROL_HW;
    dte_config.uart_config.rx_buffer_size = 1024;
    dte_config.uart_config.tx_buffer_size = 512;
    dte_config.uart_config.event_queue_size = 30;
    dte_config.uart_config.baud_rate = 115200;
    dte_config.task_stack_size = 4096;
    dte_config.task_priority = 5;
    dte_config.dte_buffer_size = 512;

    ESP_LOGI(TAG, "Initializing esp_modem for the BG95 module...");
    // Create DTE first
    dte = esp_modem::create_uart_dte(&dte_config);
    if (!dte) {
        ESP_LOGE(TAG, "Failed to create UART DTE");
        return;
    }
    ESP_LOGI(TAG, "UART DTE created successfully");
    vTaskDelay(pdMS_TO_TICKS(1000));

    // Create DCE using the DTE
    //dce = esp_modem::create_generic_dce(&dce_config, dte, esp_netif);
    dce = create_BG95_GNSS_dce(&dce_config, dte, esp_netif);
    if (!dce) {
        ESP_LOGE(TAG, "Failed to create generic DCE");
        return;
    }
    ESP_LOGI(TAG, "Generic DCE created successfully");
    vTaskDelay(pdMS_TO_TICKS(1000));

    //stop the ppp connection

    // Now that DTE/DCE are initialized, register for events
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &on_ip_event, this));
    ESP_ERROR_CHECK(esp_event_handler_register(NETIF_PPP_STATUS, ESP_EVENT_ANY_ID, &on_ppp_changed, this));


    // Set the read callback BEFORE setting CMUX mode
    dte->set_read_cb(read_callback);
    
   

    // Set flow control if needed
    if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
        auto result = dce->set_flow_control(0, 0);
        if (result != esp_modem::command_result::OK) {
            ESP_LOGE(TAG, "Failed to set flow control");
        } else {
            ESP_LOGI(TAG, "HW flow control OK");
        }
    }
    vTaskDelay(pdMS_TO_TICKS(1000));



   

    // Initial sync and basic AT commands
    auto sync_result = dce->sync();
    if(sync_result != esp_modem::command_result::OK) {
        ESP_LOGE(TAG, "Failed to sync");
    } else {
        ESP_LOGI(TAG, "Sync OK");
    }
    vTaskDelay(pdMS_TO_TICKS(1000));

    // Check network registration before setting CMUX mode
    std::string response;
    if (dce->at("AT+CREG?", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Network registration status: %s", response.c_str());
    }
    vTaskDelay(pdMS_TO_TICKS(1000));

    // Only set CMUX mode after all direct UART operations are complete
    bool cmux_mode_set = dce->set_mode(esp_modem::modem_mode::CMUX_MODE);
    if(!cmux_mode_set) {
        ESP_LOGE(TAG, "Failed to set CMUX mode");
    } else {
        ESP_LOGI(TAG, "CMUX mode set successfully");
    }
    vTaskDelay(pdMS_TO_TICKS(2000));

    //set the read callbacks again 
    dce->set_urc([this](uint8_t *data, size_t len) {
        return this->urc_callback(data, len);
    });


    // Rest of the initialization (getting IMSI, IMEI, etc.)
    //Get basic module information
    std::string imsi;
    if (dce->get_imsi(imsi) != esp_modem::command_result::OK) {
        ESP_LOGE(TAG, "Failed to get IMSI are you sure the module has a sim card?");
    } else {
        ESP_LOGI(TAG, "IMSI: %s", imsi.c_str());
        this->imsi = imsi;
    }

    std::string imei;
    if (dce->get_imei(imei) != esp_modem::command_result::OK) {
        ESP_LOGE(TAG, "Failed to get IMEI");
    } else {
        ESP_LOGI(TAG, "IMEI: %s", imei.c_str());
        this->imei = imei;
    }

    std::string module_name;
    if (dce->get_module_name(module_name) != esp_modem::command_result::OK) {
        ESP_LOGE(TAG, "Failed to get module name");
    } else {
        ESP_LOGI(TAG, "Module name: %s", module_name.c_str());
        this->modelString = module_name;
    }

    // Get firmware version using AT+CGMR
    if (dce->at("AT+CGMR", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Firmware version: %s", response.c_str());
        this->firmwareVersion = response;
    } else {
        ESP_LOGE(TAG, "Failed to get firmware version");
    }

    // Get ICCID using AT+QCCID
    if (dce->at("AT+QCCID", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "ICCID: %s", response.c_str());
        this->iccid = response;
    } else {
        ESP_LOGE(TAG, "Failed to get ICCID");
    }

    // Get manufacturer identification using AT+CGMI
    if (dce->at("AT+CGMI", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Manufacturer: %s", response.c_str());
        // Store in a new member variable if needed
    } else {
        ESP_LOGE(TAG, "Failed to get manufacturer identification");
    }

    // Get model identification using AT+CGMM
    if (dce->at("AT+CGMM", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Model: %s", response.c_str());
        // Store in a new member variable if needed
    } else {
        ESP_LOGE(TAG, "Failed to get model identification");
    }

    //get the signal quality 
    int rssi, ber;
    auto result = dce->get_signal_quality(rssi, ber);
    if (result == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Signal quality: RSSI=%d, BER=%d", rssi, ber);
    } else {
        ESP_LOGE(TAG, "Failed to get signal quality");
    }

    //get the network attachement state
    int attachment_state = 0;
    auto resultNetworkAttachment = dce->get_network_attachment_state(attachment_state);
    if(resultNetworkAttachment != esp_modem::command_result::OK){
        ESP_LOGE(TAG, "Failed to get network attachement state");
    } else {
        ESP_LOGI(TAG, "Network attachement state: %d", attachment_state);
    }


     std::string responseNetworkRegistration;
    ESP_LOGI(TAG, "Enabling network status URCs...");
    
    // Enable Circuit Switched network registration URC with location info
    if (dce->at("AT+CREG=2", responseNetworkRegistration, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "Circuit Switched network registration URCs enabled");
    } else {
        ESP_LOGE(TAG, "Failed to enable CREG URCs");
    }
    
    // Enable GPRS network registration URC with location info
    if (dce->at("AT+CGREG=2", responseNetworkRegistration, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "GPRS network registration URCs enabled");
    } else {
        ESP_LOGE(TAG, "Failed to enable CGREG URCs");
    }

    //Enable AT+CEREG which is EPS Network Registration Status
    if (dce->at("AT+CEREG=2", responseNetworkRegistration, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "EPS Network Registration Status enabled");
    } else {
        ESP_LOGE(TAG, "Failed to enable EPS Network Registration Status");
    }
    
    // Enable GPRS event reporting
    if (dce->at("AT+CGEREP=2,1", responseNetworkRegistration, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "GPRS event reporting enabled");
    } else {
        ESP_LOGE(TAG, "Failed to enable GPRS event reporting");
    }


}

BG95::~BG95() {
    if (esp_netif) {
        esp_netif_destroy(esp_netif);
    }
    if (event_group) {
        vEventGroupDelete(event_group);
    }
}

bool BG95::connect() {
    ESP_LOGI(TAG, "Connecting to cellular network this could take up to %d seconds", MAX_CONNECT_TIMEOUT/1000);
    //esp_modem::command_result result = dce->set_data_mode();
    //if (result != esp_modem::command_result::OK) {
    //    ESP_LOGE(TAG, "Failed to set data mode with error code %d", result);
    //    if (callbacks) {
    //        callbacks->cellularNetworkFailedToConnect(this);
    //    }
    //    return false;
    //}

    
    
    // Wait for connection event
    EventBits_t bits = xEventGroupWaitBits(event_group,
                                          CONNECT_BIT | ERROR_BIT,
                                          pdFALSE,
                                          pdFALSE,
                                          pdMS_TO_TICKS(MAX_CONNECT_TIMEOUT));
    
    // Handle timeout case
    if (bits == 0) {
        ESP_LOGW(TAG, "Connection attempt timed out after %d seconds", MAX_CONNECT_TIMEOUT/1000);
        if (callbacks) {
            callbacks->cellularNetworkFailedToConnect(this);
        }
        return false;
    }
    
    // Handle error case
    if (bits & ERROR_BIT) {
        ESP_LOGW(TAG, "Connection attempt failed with error");
        return false;
    }
                                          
    return (bits & CONNECT_BIT) != 0;
}

bool BG95::disconnect() {
    esp_modem::command_result result = dce->set_command_mode();
    if (result != esp_modem::command_result::OK) {
        return false;
    }
    
    return true;
}

bool BG95::isConnected() {
    return (xEventGroupGetBits(event_group) & CONNECT_BIT) != 0;
}

int BG95::getSignalQuality() {
    int rssi, ber;
    auto result = dce->get_signal_quality(rssi, ber);
    if (result == esp_modem::command_result::OK) {
        if (callbacks) {
            callbacks->cellularSignalQualityChanged(this, rssi);
        }
        return rssi;
    }
    return -1;
}




void BG95::powerUp(){
    ESP_LOGI(TAG, "Powering up the BG96 module...");
    // this needs to be low for at least 500 ms to power up the module after this happens After STATUS pin outputs
    // a high voltage level, PWRKEY pin can be released.
   // gpio_set_level(GPIO_NUM_10, 0);
   // vTaskDelay(550 / portTICK_PERIOD_MS);
    //gpio_set_level(GPIO_NUM_10, 1);

    //set the power up pin to high this is specific to this dev board - this is fucking retarted you have to connect the 5v and the 3.3v to the module
    //also this is not what the BG96 datasheet says to do
    gpio_set_level(GPIO_NUM_10, 1);
}

void BG95::powerDown(){
    // Drive PWRKEY low at least 650 ms and then release it, so that the module will execute power-down
    // procedure. The power-down scenario is illustrated in the following figure.
    ESP_LOGI(TAG, "Powering down the BG96 module...");
    gpio_set_level(GPIO_NUM_10, 0);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    gpio_set_level(GPIO_NUM_10, 1);
}

//we can handle the urcs here
esp_modem::command_result BG95::urc_callback(uint8_t *data, size_t len) {
    ESP_LOGI(TAG, "URC received: %.*s", len, data);

    if(strstr((char*)data, "+CREG:") != NULL){
        ESP_LOGI(TAG, "Network registration status: %s", data);
        //set the connected bit
        xEventGroupSetBits(event_group, CONNECT_BIT);
        //try to ping
        this->ping("google.com", 3, 1000, 5000);
    }
    
    return esp_modem::command_result::OK;
}

bool BG95::ping(const char* host, int count, int interval_ms, int timeout_ms) {
    //delay 5 seconds
    vTaskDelay(pdMS_TO_TICKS(5000));
    if (!isConnected()) {
        ESP_LOGE(TAG, "Cannot ping: not connected to network");
        return false;
    }

    // Configure ping parameters
    ip_addr_t target_addr;
    esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG();
    
    // Resolve hostname to IP
    struct hostent *he = lwip_gethostbyname(host);
    if (he == NULL) {
        ESP_LOGE(TAG, "DNS lookup failed for %s", host);
        return false;
    }

    // Copy IP address from hostent to ip_addr_t
    memcpy(&target_addr, he->h_addr, sizeof(ip_addr_t));
    
    ping_config.target_addr = target_addr;
    ping_config.count = count;
    ping_config.interval_ms = interval_ms;
    ping_config.timeout_ms = timeout_ms;
    ping_config.task_stack_size = 4096;
    ping_config.task_prio = 2;

    // Ping callbacks
    esp_ping_callbacks_t cbs = {
        .on_ping_success = [](esp_ping_handle_t hdl, void *args) {
            uint8_t ttl;
            uint16_t seqno;
            uint32_t elapsed_time, recv_len;
            ip_addr_t target_addr;
            esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
            esp_ping_get_profile(hdl, ESP_PING_PROF_TTL, &ttl, sizeof(ttl));
            esp_ping_get_profile(hdl, ESP_PING_PROF_IPADDR, &target_addr, sizeof(target_addr));
            esp_ping_get_profile(hdl, ESP_PING_PROF_SIZE, &recv_len, sizeof(recv_len));
            esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &elapsed_time, sizeof(elapsed_time));
            ESP_LOGI(TAG, "Ping success: seq=%d ttl=%d time=%lu ms", seqno, ttl, elapsed_time);
        },
        .on_ping_timeout = [](esp_ping_handle_t hdl, void *args) {
            uint16_t seqno;
            esp_ping_get_profile(hdl, ESP_PING_PROF_SEQNO, &seqno, sizeof(seqno));
            ESP_LOGI(TAG, "Ping timeout: seq=%d", seqno);
        },
        .on_ping_end = [](esp_ping_handle_t hdl, void *args) {
            uint32_t transmitted;
            uint32_t received;
            uint32_t total_time_ms;
            esp_ping_get_profile(hdl, ESP_PING_PROF_REQUEST, &transmitted, sizeof(transmitted));
            esp_ping_get_profile(hdl, ESP_PING_PROF_REPLY, &received, sizeof(received));
            esp_ping_get_profile(hdl, ESP_PING_PROF_DURATION, &total_time_ms, sizeof(total_time_ms));
            ESP_LOGI(TAG, "Ping statistics: %lu packets transmitted, %lu received, time %lu ms", 
                     transmitted, received, total_time_ms);
        }
    };

    esp_ping_handle_t ping;
    ESP_ERROR_CHECK(esp_ping_new_session(&ping_config, &cbs, &ping));
    ESP_ERROR_CHECK(esp_ping_start(ping));
    
    return true;
}



//method used to request gnss data from the module 
bool BG95::requestGnssData() {
    //first turn on the gnss power with AT+QGPS 
    std::string response;
    if (dce->at("AT+QGPS=1", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "GNSS power turned on");
    } else {
        ESP_LOGE(TAG, "Failed to turn on GNSS power");
        //return false;
    }

    //then request the data AT+QGPSLOC 
    if (dce->at("AT+QGPSLOC", response, 1000) == esp_modem::command_result::OK) {
        ESP_LOGI(TAG, "GNSS data requested");
    } else {
        ESP_LOGE(TAG, "Failed to request GNSS data");
        //return false;
    }

    return true;
}

@michaelboeding
Copy link
Author

Hey @david-cermak any support on this?

Ok I have made more progress on this. It seems like I have now setup CMUX correctly and set the URC handler so that I get the URCs after entering CMUX mode.

But I still have this weird ppp issue....basically what I'm trying to accomplish is the following.

  1. Setup the Module in CMUX mode
  2. Setup the AT commands to inform me via URCs of the changes in network status as events.
  3. Once I get the +CREG (or any other related network status URC) I want to then make sure the networks interface for ppp is up but I can't seem to get this to work?
  4. I would like to handle changes in network status from the URC to pause/start/resume the network interface.
  5. I will also want to be sending the message to get the GNSS data from the BG95 but I do think I have that figured out unless there is need for another virtual terminal for that in CMUX mode? I would assume you could just do this over the command terminal?

Do I need to be handling the multiple terminals myself? I'm a little lost at this point and haven't been able to find any example that shows exactly what I want here unless I'm misunderstanding something? Any help would be greatly appreciated. @david-cermak . Also important to note that if my module gets its network up and then I restart the program it will work for connecting to PPP.

Hey @david-cermak any support on this?

@david-cermak
Copy link
Collaborator

I think the problem is in here:

esp_modem::command_result BG95::urc_callback(uint8_t *data, size_t len) {
    ESP_LOGI(TAG, "URC received: %.*s", len, data);

    if(strstr((char*)data, "+CREG:") != NULL){
        ESP_LOGI(TAG, "Network registration status: %s", data);
        //set the connected bit
        xEventGroupSetBits(event_group, CONNECT_BIT);
        //try to ping
        this->ping("google.com", 3, 1000, 5000);
    }
    
    return esp_modem::command_result::OK;
}

this is the URC callback, which is called directly from the modem thread, and you're actually waiting 5 seconds if I'm not mistaken stalling the modem service, correct?

Suggest leaving the event group signal in the callback

        xEventGroupSetBits(event_group, CONNECT_BIT);

and moving the ping method to be called upon the signal notification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Feature Request Feature Request for esp-protocols
Projects
None yet
Development

No branches or pull requests

3 participants