AprilBrother / cactus-micro

Cactus Micro - a tiny size arduino compatible board plus WIFI chip esp8266.
12 stars 5 forks source link

A simple http POST example #1

Closed xseignard closed 8 years ago

xseignard commented 9 years ago

Hello,

I just recieved the cactus micro board and it seems pretty promising!

But I'm trying to do a HTTP POST from the board to a distant server, but I can't find any documentation/examples about it.

I managed to connect to wifi following the temperature logger example, but cannot perform a HTTP POST.

Any examples available?

Regards,

Xavier

volca commented 9 years ago

I will make an example these days.

xseignard commented 9 years ago

Thanks! This is more than welcomed!

Regards,

Xavier

xseignard commented 9 years ago

So i tried myself and went there https://gist.github.com/xseignard/a650f241b434eb1b296a

I can connect to the wifi, but I cannot initiate the TCP connection, any idea?

Regards

volca commented 9 years ago

I'm writing a library to handle http request. I will check your code today.

xseignard commented 9 years ago

I checked your comments and tried your tips, but i still cannot POST. The TCP connection seems to fail. I use a simple node.js/express.js server to receive the posts:

var express = require('express'),
    bodyParser = require('body-parser'),
    app = express();

app.use(bodyParser.urlencoded({ extended: false }));

app.get('/', function (req, res) {
    res.send('Hello World!');
});

app.post('/event', function(req, res) {
    console.log(req.body);
    res.status(200).send();
});

var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log('Example app listening at http://%s:%s', host, port);
});

And I can reach this server with the following:

 curl -X POST -d "data=42" http://192.168.1.24:3000/event
xseignard commented 9 years ago

With that tiny script I can send AT commands from arduino monitor

#include <SoftwareSerial.h>

// ESP8266 rx, tx
SoftwareSerial esp8266(11, 12);

void setup() {
  delay(5000);
  Serial.begin(9600);
  esp8266.begin(9600);
  // enable wifi
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  delay(1000);
}

void loop()
{
  if (Serial.available() > 0) {
    char ch = Serial.read();
    esp8266.print(ch);
  }
  while (esp8266.available() > 0) {
    char ch = esp8266.read();
    Serial.print(ch);
  }
}

So I tried to send a AT+CIPSTART="TCP","192.168.1.24",3000 and here was the result:

CONNECT

OK

So it seems it should work for my initial sketch too since i'm trying to find "OK" in the buffer, I also tried to find "CONNECT" with no more success.

I really don't get it, and if i cannot initiate a TCP connection, the cactus micro is just a plain old arduino micro...

Here is the result of a AT+GMR

00200.9.5(b1)
compiled @ Dec 25 2014 21:40:28
AI-THIN

I'm really stuck here...

volca commented 9 years ago

I'm testing HTTP post code these days but no luck. The problem is it always lose the "\r\n\r\n" in the POST content.

But for HTTP get, it works well.

I wrote a blog How to change the serial port for Cactus Micro. Use hardware serial port is much stable than software serial.

xseignard commented 9 years ago

Any idea why I cannot initiate the TCP connection from my arduino code, but I can when I type the AT command directly?

volca commented 9 years ago

I think the module haven't got IP when you tried to create TCP connection. Please add a delay(5000) after joined AP.

xseignard commented 9 years ago

Thanks, i can now initiate a TCP connection

Here is my code for now:

#include <SoftwareSerial.h>

// ESP8266 rx, tx
SoftwareSerial esp8266(11, 12);

void setup() {
    //connection to ESP8266
    esp8266.begin(9600);
    esp8266.setTimeout(2000);
    //serial debug
    Serial.begin(9600);

    // enable wifi
    pinMode(13, OUTPUT);
    digitalWrite(13, HIGH);
    delay(1000);

    if (check()) {
        resetESP8266();

        if (connectWifi("crepeFlambee", "!rfvcde1984")) {
            delay(5000);
            String response="";
            boolean ok = httpPOST("test=42", "192.168.1.24", 3000, "/event", &response);
            if (ok) {
                Serial.println(response);
            }
            else {
                Serial.println("Something went wrong while posting data");
            }
        }
    }
}

void loop() {
}

boolean check() {
    esp8266.println("AT");
    Serial.println("checking..");
    boolean ok = false;
    if (esp8266.find("OK")) {
        Serial.println("ESP8266 available");
        ok = true;
    }
    return ok;
}

void resetESP8266() {
    // reset ESP8266
    esp8266.println("AT+RST");
    delay(500);
    // set station mode
    esp8266.println("AT+CWMODE=1");
    delay(200);
    // set single connection mode
    esp8266.println("AT+CIPMUX=0");
    delay(200);
}

boolean connectWifi(String ssid, String password) {
    String cmd = "AT+CWJAP=\"" + ssid + "\",\"" + password + "\"";
    esp8266.println(cmd);
    if(esp8266.find("OK")) {
        Serial.println("Connected!");
        return true;
    }
    else {
        Serial.println("Cannot connect to wifi");
        return false;
    }
}

boolean httpPOST(String data, String server, int port, String uri, String* response) {
    // initiate TCP connection
    String tcpStart = "AT+CIPSTART=\"TCP\",\"" + server + "\"," + port;
    Serial.println(tcpStart);
    // prepare the data to be posted
    String postRequest =
        "POST " + uri + " HTTP/1.1\r\n" +
        "Host: " + server + ":" + port + "\r\n" +
        "Accept: *" + "/" + "*\r\n" +
        "Content-Length: " + data.length() + "\r\n" +
        "Content-Type: application/x-www-form-urlencoded\r\n" +
        "\r\n" +
        data;

    // notify ESP8266 about the lenght of TCP packet
    String sendCmd = "AT+CIPSEND=" + postRequest.length();

    esp8266.println(tcpStart);
    if (esp8266.find("OK")) {
        Serial.println("TCP connection OK");
        esp8266.println(sendCmd);
        if (esp8266.find(">")) {
            Serial.println("Sending packet...");
            esp8266.println(postRequest);
            if (esp8266.find("SEND OK")) {
                Serial.println("Packet sent");
                while (esp8266.available()) {
                    String tmpResp = esp8266.readString();
                    response = &tmpResp;
                }
                // close the connection
                esp8266.println("AT+CIPCLOSE");
                return true;
            }
            else {
                Serial.println("An error occured while sending packet");
                return false;
            }
        }
        else {
            Serial.println("ESP8266 is not listening for incoming data");
            return false;
        }
    }
    else {
        Serial.println("Cannot initiate TCP connection");
        return false;
    }
}

Now I face the problem that I never find the > char telling the arduino it can start sending data. The road to POST with cactus micro is bumpy...

volca commented 9 years ago

I have made a http post sample today. I will re-organize the code tomorrow. The key function is F().

For example:

Serial1.println(F("AT+CIPSEND=100"));

It will save the string to flash and not ram.

volca commented 9 years ago

Hi,

I add a blog and a simple example for how to make http request. Please have a try.

xseignard commented 9 years ago

Hello, I don't see why you need to use the F macro?? Since the length of a tcp packet is variable it makes no sense to use the F macro

xseignard commented 9 years ago

I checked your blog post, the cactus micro is definitely not IOT ready... I'll give a try someday

xseignard commented 9 years ago

Any updates?

volca commented 9 years ago

Hi,

I have added a httpPost eample. Please have a look.

We are also testing the next revision Cactus Micro. The new version is make the hardware serial as default option.

I'd like to send you a free sample.

xmoulin commented 9 years ago

Hello, I just try the HTTP Post Example, with Arduino 1.6.5 IDE, and I got some errors:

cactus-httpPost:49: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:49: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:49: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost.ino: In function 'bool connectWifi()': cactus-httpPost:94: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:94: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost.ino: In function 'void setup()': cactus-httpPost:133: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:133: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:133: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost.ino: In function 'void httpPost(String)': cactus-httpPost:194: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:194: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:205: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:205: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' cactus-httpPost:205: error: converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)' converting to 'String' from initializer list would use explicit constructor 'String::String(int, unsigned char)'

pgmspace.h have change between version 1.0.6 and 1.5.6. some post about that: http://forum.arduino.cc/index.php?topic=273294.0

Regards, Xavier.

volca commented 9 years ago

Thank you for your reminder!

hulvejen commented 8 years ago

The httpPost eample. is displaying 404. Please update the link.

volca commented 8 years ago

Thank you. Link is fixed.

loki077 commented 8 years ago

Thank you in advance ............for all this discussions ............:) The example links no more there if you can plzz try to post it back. I am also trying the POST command but its not working it seems same to me that ESP8266 is not taking /r/n command from all your discussion i get to understand that its an firm ware issue am i right? ?/????

volca commented 8 years ago

when did you buy the cactus micro? For rev2, the default firmware is ESPduino on ESP8266. Please try the rest.ino sketch.

ArthurTimmermans commented 6 years ago

You have to put some delays between your esp8266 calls, makes it more stable and you do not come further than:

if (esp8266.find(">")) {

because you have to make the command above a string.

String sendCmd = "AT+CIPSEND=" + String(postRequest.length());