Read UART via Agent Function

I’ve been playing around with sending serial requests to a device from the agent. What I would like to do is create a agent function that when called, sends the parameters to the device, device issues a command on the UART and then waits for a response which is returned to agent. Sounds simple enough but implementation is a little more difficult…

By the way I have gotten this to work with http requests but not with regular function calls.

Here is a example of a functional HTTP request:

Now here is the example of using a regular function. This does not work as expected:

I think that I know why it is not working, because the agent will not actually wait for lines 11-13 to complete before line 14 executes and returns the content of “uart_response” at that moment in time.

Soooo, is it possible to make a command like this? And how?

I think this is how it could work - note this is just a quick and dirty code hack. Welcome comment in case I got it all wrong.

So as per your second example… Basically the problem with the Agent is that it will send your UART command to Device… as shown in example device.send("req", cmd) and then moves on to the deal with the next event. There is no default method where it stops and waits for a reponse as you get with html.

So in this case I would suggest create a dual messaging format where you have some value that is stored and monitored in the Agent Code. To do that I suggest making “cmd” an object and not a string such as:
cmd = {"id": CmdCounter, "UARTmsg": "YOURCOMMAND"}

Then you would need to have a global object or an array in the Agent code that you use to store the CmdCounter value and you will then have another function to monitor when the device returns the CmdCounter back to the agent to close the loop, so to speak. For example:

Global_cmds = {"id": CmdCounter, "ConfirmationReceived": false}

Then in Device code you have a handler for “req” as given in the example agent.on("req", getRequest);

Then in the getRequest function you would have something like:
function getRequest(cmd) { server.log("Requesting"+cmd.UARmsg); AgentCmdID = cmd.id; // where AgentCmdID is declare a global in device code // You need to do this to allow the "id" to be referenced in the other device function that reads the response from the UART serial RX rxBuffer = "" uart.write(soh); uart.write(cmd); uart.write(etx); }

Then in function function dataRx() you would append something like this at the bottom of the function

function dataRx() { ....... else { local AgentMsg = {"id":AgentCmdID, "rxBufferMsg": rxBuffer}; agent.send("resp", AgentMsg ) }

Then in the agent code you would have a response handler:

`
function DeviceMsgResponseHandler(DeviceMsg)
{
// Check that the ID’s match in the Agent global
if (Global_cmds.id == DeviceMsg.id) {
// you have now got a valid response
Global_cmds.ConfirmationReceived = true;
}
}

device.on(“resp”, DeviceMsgResponseHandler);
`

You can also add in time value to track how long this feedback loop takes.

You could then also add in a watchdog function the monitors this time and have a timeout handler to manage the case when the device fails to return a response.

Reading the UART via the agent and performing other other operations on the device is possible. I do this extensively. I can’t share the code but I can describe an effective approach

I’ve implemented a form of RPC that allows the agent to invoke functions on the device. Everything needs to run asynchronously, so you need to pass a callback in every invocation. gerriko is right that you’ll need to uniquely identify each request so that you can keep track of them. A response may or may not be returned from the device, so you’ll need to manage timeouts and callbacks may return errors, instead of results. Alternately, beardedinventor has posted a basic framework called Bullwinkle in github that could be a good starting point for you. It handles some of these details.

Not directly related, but could be helpful; Aron wrote this demo code a while back, it’s for a web serial console. The imp does line buffering and the agent provides a web UI that allows you to view serial data and send commands.

Thanks everyone for the messages, they are very helpful suggestions. I was hoping that I was missing something simple but it sounds like some infrastructure on my part needs to be built out for this function.

The idea of a request/response queue seems ok, I think that routing the response data would be cumbersome compared to my ultimate ideal:

response = getUartData(cmd)

I feel like this is a hack but I sort of like the simplicity, I was thinking about using the original http cmd response code as shown then have the agent call its own api via http. I might explore that further…

Funny side story, last night I did try to implement a mutex like function with a global variable and a while loop and failed miserably locking up the imp until morning :slight_smile:
https://discourse.electricimp.com/discussion/2043/imp-stuck-in-while-true-loop-won-t-download-new-code#latest

Bullwinkle looks great but I’m not convinced that it will help me in this instance because it too does not wait to get data from the UART.

The UART Web app is interesting, there is some advanced Squirrel Code in there! I had to run it in order to start to understand all that is going on. Still thinking on that one.

I really appreciate the help, I’ll keep at it and see what feels right.

No luck on calling my own API via the agent http.get, seems to lock up.

Going to write a UART data receptor that is asynchronous from the requestor now. Thanks :slight_smile:

Making everything asynchronous can be a pain at first, but it makes Squirrel far more flexible, responsive and powerful.

Agree with the power of asynchronous coding in most instances, I’m just trying to think of how I can easily do what I need to do with it.

It doesn’t get more simple than:
response = getUartData(cmd)

I was able to get some code working that doesn’t rely on this however.