Page 1 of 1

[Solved] How to send HTTP POST request via Lua Script?

Posted: Thu Apr 30, 2020 7:24 pm
by GTIspirit
How can we send an HTTP POST request to connected WiFi client via Lua Script?

So if I want to say use Chrome extension SERVISTATE to send commands to a WiFi client via POST request, how do we do it?

Here's another example of what it looks like:
https://forums.garmin.com/apps-software ... reless-api

@brentp this is all it takes to Start and Stop recording of Garmin Virb. Oh so close.....

Posted: Tue May 12, 2020 8:23 pm
by brentp
To do this you'd have to turn off WiFi (so RCP isn't trying to control it) and then issue direct AT commands to the WiFi module in RC.

See the bottom of the page here:
https://wiki.autosportlabs.com/AutomaticCameraControl

The WiFi module is an ESP8266, so you'll be able to find information on the web on how to perform HTTP POST commands.

Let us know what you find out!

Posted: Thu May 14, 2020 6:32 pm
by GTIspirit
Boo ya, got it!

to start recording:

Code: Select all

function startRecording()
  sendAt('AT+CIPSTART="TCP","192.168.0.1",80')
  sleep(2000)
  local crlf = string.char(13) ..string.char(10)
  local post = 'POST /virb HTTP/1.1\r\nHost: 192.168.0.1\r\nAccept: */*\r\nContent-Length: 28\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n{"command":"stopRecording"}\r\n' ..crlf ..crlf
  sendAt('AT+CIPSEND=' ..toInt(#post))
  sleep(1500)
  sendRaw(post)
println(post)
  sleep(5000)
  sendAt('AT+CIPCLOSE') 
end
to stop recording:

Code: Select all

function startRecording()
  sendAt('AT+CIPSTART="TCP","192.168.0.1",80')
  sleep(2000)
  local crlf = string.char(13) ..string.char(10)
  local post = 'POST /virb HTTP/1.1\r\nHost: 192.168.0.1\r\nAccept: */*\r\nContent-Length: 28\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n{"command":"stopRecording"}\r\n' ..crlf ..crlf
  sendAt('AT+CIPSEND=' ..toInt(#post))
  sleep(1500)
  sendRaw(post)
println(post)
  sleep(5000)
  sendAt('AT+CIPCLOSE') 
end
Turns out, the Virb is picky about character indents at the start of each subsequent line. I had followed some examples found by Googling "esp8266 http post request at command" and had an extra space between \r\n and start of next line. I saw this with the println command, but didn't realize this makes a difference. Took out that space and voila, it works!

Now to skinny up the code since the Garmin API syntax is the same up to the command. According to API, this can be "status" "startRecording" "stopRecording" etc.

Posted: Thu May 14, 2020 6:44 pm
by brentp
That's great. Would you be interested in updating our wiki docs with this information?
https://wiki.autosportlabs.com/AutomaticCameraControl

If so, we'll open up wiki access to allow you to edit. email [email protected] to coordinate.

Posted: Fri May 15, 2020 12:02 pm
by GTIspirit
Sure, happy to contribute and update the Wiki.

Meanwhile, here's some more info on the POST command.

The Postman program was super helpful to figuring this out. The easy part is simply sending the command via the Postman command line.

What was really helpful was using the Postman feature to view the "code"

Then as @brentp suggested, I Googled "esp8266 http post request at command" Careful with the results, because some of them pertain to GET command, not POST command. (For reference, GET is what the GoPro Hero uses.)

These were the two most helpful hits for me to get this figured out.
https://stackoverflow.com/questions/406 ... an-esp8266
https://stackoverflow.com/questions/406 ... an-esp8266

After getting the above fixed command to work I came up with this more generic POST function.

Code: Select all

function postCommand(cmd)
  sendAt('AT+CIPSTART="TCP","192.168.0.1",80')
  sleep(500)
  local crlf = string.char(13) ..string.char(10)
  local post = 'POST /virb HTTP/1.1\r\nHost: 192.168.0.1\r\nAccept: */*\r\nContent-Length: ' ..toInt(#cmd)..'\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n' ..cmd ..'\r\n' ..crlf ..crlf
  sendAt('AT+CIPSEND=' ..toInt(#post))
  sleep(100)
  sendRaw(post)
  println(post)
  sleep(100)
  sendAt('AT+CIPCLOSE') 
end
It works by passing the required arguments to the postCommand function, e.g.:

Code: Select all

postCommand('{"command":"startRecording"}')
or

Code: Select all

postCommand('{"command":"stopRecording"}')
The Virb didn't seem to care if the command length was correct or not. e.g.
{"command":"startRecording"} is 28 characters, and
{"command":"stopRecording"} is 27 characters.

This corresponds to the Content-Length: value

But I kept this in there in case it matters for other devices. So now you can have fun trying this out to send info to other WiFi connected devices. :D