Getting a cloud function to wait for the response on Serial1
I have a Particle Electron setup to communicate with an external system using serial communication over Serial1. I have everything working and I’m now trying to refine the functionality, and I have a problem that I’ve not been able to solve. I’m not an experienced programmer so I don’t fully understand everything that I’m doing. It’s lot of trial and error.
I’m using serialEvent1 to monitor Serial1 and process incoming data. I also have a cloud function for sending a command over Serial1. The function in serialEvent1 will pick up the response and process it. I would expect an ACK in this case. The thing is that I want to stay in the cloud function to wait for the response (the ACK) over Serial1 before I return the result of the cloud function.
I have tried to read the response over Serial1 inside of the cloud function but it seems that serialEvent1 is picking up the data before I can get to it in the cloud function. I need to have serialEvent1 to process data that is received at other times, not as response to the cloud function. Maybe this could also be done in the application loop.
I think it would make it easier if I could understand how loop(), serialEvent1() and the cloud function interacts with each other in terms of processing. Because I’m not using threading I would expect that serialEvent1 should not be triggered as long as I’m still executing the code in the cloud function but it doesn’t seem that way because it appears that serialEvent1 is picking up the response while I’m still waiting for it in the cloud function.
Any thoughts on this or is my description only confusing?
For one, waiting in a Particle.function() is not a good idea and is frowned upon (also by the calling instance, since the request may timeout). Particle.functions() are meant to trigger actions and the return value should indicate if that trigger succeeded but not neccessarily the triggered action (if it happens to be a longer running one).
So you’d rather set a flag inside your “cloud function” that will “alter” the normal behaviour of loop() or serialEvent1() to deal with the expected ACK and then send the data via Serial1 and return from the “cloud function”.
As for the sequence how loop(), serialEvent1() and Particle.function()s are called. It’s easy for the first two.
First loop() gets executed, after that serialEvent() then serialEvent1() and so on and then back to loop()
For Particle.function()s it’s not that easy.
They can be executed at any time when the cloud task gets executed, which happens between loop() iterations, or every accumulated second spent in delay(), or when you call Particle.process(), or with SYSTEM_THREAD(ENABLED) at some other time too.
Thank you for that good explanation! I totally understand what you are pointing out and it makes perfect sense.
However then I have another problem. How can I know (in my mobile app) when the command has been received and processed by the external system? The thing is that after the command has the been received and and processed by the external system I will have to execute another function to update a cloud variable with the new values and then fetch that cloud variable from my mobile app. How will I now when that variable has been updated without polling it over and over again? Any suggestions?
Thank you! I tried this and got it to work. I still have some trouble with the Android app because it seems it doesn’t manage to catch the events every time but I will continue to look into that.