UDP COAP not working when Cloud not connected

We are using COAP to connect to our own server and bypass the Particle Cloud. As such, it isn’t critical that the connection to Particle Cloud succeeds for normal operation (We are using it for OTA updates, but that isn’t a core functionality).

To allow us control over the Particle Cloud connection, the systemMode is MANUAL and we are using the systemThread. I have tried both 0.7.0 and the 0.8.0 rc-4 System Firmware.

We have had some issues with Cloud keys expiring on the particles (IE constant Cyan Blinking). To mitigate this, we have added a timeout for Particle.connect() using waitFor. If the device can’t establish a cloud connection soon enough, it stops connecting and starts up. In this case, the device breaths Green.

There are 2 problems that we are having. First is that I am not 100% sure that the waitFor code that I am using is correctly pickup the connection. I believe that this problem will be resolved by Particle.connect(timeout, retryDelay) if the feature is ever implemented. However some feedback on the code below would be helpful.

bool connectParticle() {
    
    if (! flag_particle_connecting) {
        Serial.println("Connecting to Particle");
        flag_particle_connecting = true;
        Particle.connect();
    }
    return Particle.connected();
}

void setup() {
        //Celluar on and connect is here
        Serial.println("Connected to Network"); 

        //Try to connect to Particle
        flag_particle_connecting = false;
        if (! waitFor(connectParticle,10000)) {
            Particle.disconnect();
            Serial.println("Particle Connection failed");

            sendErrorMessage(String("Error Connecting with Particle"));
       }
}

The second problem is that if the Failed connection (above) routine runs, the UDP COAP requests that we make all fail to send. A Message ID is assigned to the message, bun no data hits our server. Occasionally, after resetting the (Celluar) connection (We reset if we get no response from any packet after 10 minutes) and trying to connect to the Particle Cloud again, we will have a dozen successful packets.

When Particle Cloud is connected, there is no issue with requests and all are processed in a prompt manner.

I have looked through the device firmware on the Particle.disconnect(); function but failed to find any link between it and the spark_wiring_udp class that is used as the base of the COAP client. Is there a relationship between these objects?

As these devices will be numerous and in remote locations, being 100% dependent on Particle Cloud being present isn’t desirable as we have had the keys issue a number of times now across a number of devices.

Not addressing the CoAP side of the question, but just some general notes.

While I don’t see a lot wrong with your connectParticle() function, I don’t quite see why you chose to do it that way.
The same thing would happen when you did this

        Serial.println("Connecting to Particle");
        Particle.connect();
        if (! waitFor(connectParticle,10000)) {
            ...
        }

This would also remove any potential risk of your code breaking in case waitFor() would be altered to expecting a different kind of function signature (e.g. Future “promises”).

Also there is no need to “cast” a string literal into a String object as done here

  sendErrorMessage(String("Error Connecting with Particle"));

Are you calling Particle.process() regularly, even when !Particle.connected()?
Are you making sure, your UDP calls do free (UDP.stop()) the sockets after they are used?

I thought Particle.connect() was blocking? Or is that only in Auto and Semi Auto.

This is the code we are using to call Particle.process(). It is called every ~4 seconds in the main loop.

if (Particle.connected()) {
       Particle.process();
 }

We are using the COAP library, but there doesn’t appear to be any mention of UDP.stop() in that library. Would I be better off clearing all the connections and restarting the COAP client occasionally as well?

Particle connect should not be blocking in MANUAL mode (and as for my own preference for the other modes neither).
However, if it was blocking, your function approach wouldn't work either as the flow would be blocked before the return call in it.

I'd call Particle.process() independet of connection status as it also does some other work in the background.

This contributed library doesn't seem to be used very widely, so if there were potential issues they probably haven't been found/reported yet.
But in case of connection problems any library using sockets should try to detect whether a free socket is available and report a lack of such. And since sockets are a limited "resource" it should be take care to free them ASAP after use.

Thanks ScruffR

If nothing else, I think my first problem is solved. I thought I was getting confused.

I will try Particle.process() with no check and see how that goes.

I will look at modifying the library next week and see where that goes.

1 Like