u-blox / ubxlib

Portable C libraries which provide APIs to build applications with u-blox products and services. Delivered as add-on to existing microcontroller and RTOS SDKs.
Apache License 2.0
287 stars 82 forks source link

SARA-R510M8S: How to use cellular network and GNSS network simultaneously? #213

Closed WyattSmithTritium closed 3 months ago

WyattSmithTritium commented 3 months ago

Hi! I'm working with the SARA-R510M8S on the ESP-IDF platform. I'm looking to get a constant location from the GNSS module while also maintaining an MQTT connection over the cellular network. I've gotten each part working independently, but once I try to do both at once, I lose the first network (GNSS or Cellular) despite which network I bring up first. I've followed some of the steps mentioned in #155 and merged it with the MQTT example.

Essentially my problem is that I can't seem to keep both networks on at the same time. I've included the main part of my code below. Any thoughts? Thank you!

static const uDeviceCfg_t gDeviceCfg = {
        .deviceType = U_DEVICE_TYPE_CELL,
        .deviceCfg = {
                .cfgCell = {
                        .moduleType = U_CFG_TEST_CELL_MODULE_TYPE,
                        .pSimPinCode = NULL,
                        .pinEnablePower = -1,
                        .pinPwrOn = -1,
                        .pinVInt = -1,
                        .pinDtrPowerSaving = -1},
        },
        .transportType = U_DEVICE_TRANSPORT_TYPE_UART,
        .transportCfg = {
                .cfgUart = {.uart = 2, .baudRate = U_CELL_UART_BAUD_RATE, .pinTxd = 21, .pinRxd = 19, .pinCts = -1, .pinRts = -1, .pPrefix = NULL},
        },
};

// NETWORK configuration for cellular
static const uNetworkCfgCell_t gNetworkCfg = {
        .type = U_NETWORK_TYPE_CELL,
        .pApn = SIM_APN,
        .timeoutSeconds = 6000,
};

// NETWORK configuration for GNSS
static const uNetworkCfgGnss_t gnssNetworkCfg = {
        .type = U_NETWORK_TYPE_GNSS,
        .moduleType = U_GNSS_MODULE_TYPE_M8,
        .devicePinPwr = -1,
        .devicePinDataReady = -1};

void init_modem(void) {
    uPortInit();
    uDeviceInit();

    // Open the device
    returnCode = uDeviceOpen(&gDeviceCfg, &devHandle);
    uPortLog("Opened device with return code %d.\n", returnCode);

    if (returnCode == 0)
    {
        uPortLog("Bringing up GNSS...\n");
        if (uNetworkInterfaceUp(devHandle, U_NETWORK_TYPE_GNSS, &gnssNetworkCfg) == 0)
        {
            uPortLog("Starting continuous location.\n");
            returnCode = uLocationGetContinuousStart(devHandle, U_GNSS_POS_STREAMED_PERIOD_DEFAULT_MS, U_LOCATION_TYPE_GNSS, NULL, NULL, gnssCallback);
            if (returnCode != 0)
            {
                uPortLog("Unable to start continuous location!\n");
            }
        }
        else
        {
            uPortLog("Unable to bring up GNSS!\n");
        }

        // Bring up the network interface
        uPortLog("Bringing up the network...\n");
        if (uNetworkInterfaceUp(devHandle, U_NETWORK_TYPE_CELL,
                                                        &gNetworkCfg) == 0)
        {
            pContext = pUMqttClientOpen(devHandle, NULL);
            if (pContext != NULL)
            {
                uPortLog("Connecting to MQTT broker \"%s\"...\n", MY_BROKER_NAME);
                if (uMqttClientConnect(pContext, &connection) == 0)
                {
                    uMqttClientSetMessageCallback(pContext, messageIndicationCallback, (void *)&messagesAvailable);

                    uSecurityGetSerialNumber(devHandle, topic);

                    xTaskCreate(mqttRead_task, "mqttRead_task", 1024 * 4, NULL, 5, &mqttRead_taskHandle);
                    returnCode = 0;

                    uPortLog("Subscribing to topic \"%s\"...\n", topic);
                    if (uMqttClientSubscribe(pContext, topic, U_MQTT_QOS_AT_MOST_ONCE))
                    {
                        uPortLog("Publishing \"%s\" to topic \"%s\"...\n",
                                         message, topic);
                        if (uMqttClientPublish(pContext, topic, message, sizeof(message) - 1, U_MQTT_QOS_AT_MOST_ONCE, false) == 0)
                        {
                            returnCode = 0;
                        }
                        else
                        {
                            uPortLog("Unable to publish our message \"%s\"!\n", message);
                        }
                    }
                    else
                    {
                        uPortLog("Unable to subscribe to topic \"%s\"!\n", topic);
                    }
                }
                else
                {
                    uPortLog("Unable to connect to MQTT broker \"%s\"!\n", MY_BROKER_NAME);
                }
            }
            else
            {
                uPortLog("Unable to create MQTT instance!\n");
            }
        }
        else
        {
            uPortLog("Unable to bring up the network!\n");
        }
    }
    else
    {
        uPortLog("Unable to bring up the device!\n");
    }
}
RobMeades commented 3 months ago

Thanks for posting, and sorry that you're having trouble with this. At a first glance your code looks fine; I think we would conventionally bring the cellular network up first, then the GNSS network, but that shouldn't make any difference.

Would you be able to post the debug output from ubxlib here, so that I can see the nature of the failure?

WyattSmithTritium commented 3 months ago

Thanks for the quick response @RobMeades. After some additional testing this morning, I've found that I actually am able to use both networks this way. Sorry for the confusion. My test is to be able to receive MQTT messages while also getting a GNSS fix.

What's interesting though, is that if I bring up cellular first and then GNSS, I am not able to receive MQTT messages. I've attached a partial log below.

I can confirm that the code above does work though, so I don't need any further help. The cell connection is more important than GNSS so I would prefer to bring it up first, but what I have will work. Thanks!

log.txt

I'm happy if you're happy, so feel free to close this issue. 🙂

RobMeades commented 3 months ago

That's excellent news. And it seems, from your log, that I have made another of those "schoolboy" errors in the MQTT example code, which is that I have:

https://github.com/u-blox/ubxlib/blob/2f39e1b03d8ecf1c0735599bed9aafecb0c98a13/example/mqtt_client/mqtt_main.c#L326-L327

...whereas of course that should be:

if (uMqttClientSubscribe(pContext, topic,
                         U_MQTT_QOS_EXACTLY_ONCE) == 0) {

D'oh! Is that what you were referring to with the "Unable to subscribe to topic" message in the attached log? Will fix...

WyattSmithTritium commented 3 months ago

Yes, thank you!

RobMeades commented 3 months ago

FYI, the MQTT example is fixed in 1c57c42930e69a7e049ab19185e8b9f1f49c2fe1: it happened to work in our case because the function can return 0, 1 or 2 (it returns the QOS of the subscription).