Arduino not talking to pachube

I tried posting this on the pachube site and still no response after 3 days so I thought I would try here.
I’m having trouble getting my Arduino to talk pachube. I'm a newbie on both the Arduino and pachube and have spent hours searching so please bear with me. I’m using the Puchube client example included with the Arduino 22 and have also tried the “Arduino Ethernet with Pachube inputs and outputs” on the pachube site. I'm using a Arduino mega2560 with a standard Ethernet shield(Wiznet W5100). My feed says it’s frozen and I have no graphs displayed. The debug page shows 0 requests but a few days ago I did get an email saying I reached my rate limit but nothing showed up on my feed. Any help would be greatly appreciated.
/*

The serial response I get is,

b5

411 Length Required

disconnecting.
connecting...
HTTP/1.1 411 Length Required
Date: Fri, 07 Oct 2011 03:07:45 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close

Pachube sensor client

This sketch connects an analog sensor to Pachube (http://www.pachube.com)
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board.

Circuit:
* Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13

created 15 March 2010
updated 4 Sep 2010
by Tom Igoe

http://www.tigoe.net/pcomp/code/category/arduinowiring/873
This code is in the public domain.

*/

#include
#include

// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
byte ip[] = {
192,168,1,123 };
byte gateway[] = {
192,168,1,1};
byte subnet[] = {
255, 255, 0, 0 };

// The address of the server you want to connect to (pachube.com):
byte server[] = {
173,203,98,29 };

// initialize the library instance:
Client client(server, 80);

long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const int postingInterval = 10000; //delay between updates to Pachube.com

void setup() {
// start the ethernet connection and serial port:
Ethernet.begin(mac, ip);
Serial.begin(9600);
// give the ethernet module time to boot up:
delay(1000);
}

void loop() {
// read the analog sensor:
int sensorReading = analogRead(A0);

// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.print(c);
}

// if there's no net connection, but there was one last time
// through the loop, then stop the client:
if (!client.connected() && lastConnected) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
}

// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
sendData(sensorReading);
}
// store the state of the connection for next time through
// the loop:
lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void sendData(int thisData) {
// if there's a successful connection:
if (client.connect()) {
Serial.println("connecting...");
// send the HTTP PUT request.
// fill in your feed address here:
client.print("PUT /api/36959.csv HTTP/1.1\n");
client.print("Host: www.pachube.com\n");
// fill in your Pachube API key here:
client.print("MY PACHUBE KEY");
client.print("Content-Length: ");

// calculate the length of the sensor reading in bytes:
int thisLength = getLength(thisData);
client.println(thisLength, DEC);

// last pieces of the HTTP PUT request:
client.print("Content-Type: text/csv\n");
client.println("Connection: close\n");

// here's the actual content of the PUT request:
client.println(thisData, DEC);

// note the time that the connection was made:
lastConnectionTime = millis();
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
}
}

// This method calculates the number of digits in the
// sensor reading. Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;
}
// return the number of digits:
return digits;
}

That 411 response code should be a big clue. Google html error codes. One result:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
where it says:

10.4.12 411 Length Required

The server refuses to accept the request without a defined Content- Length. The client MAY repeat the request if it adds a valid Content-Length header field containing the length of the message-body in the request message.

I don't know how a message could be clearer. Perhaps if it fixed your code for you...

Hi Paul thanks for the quick response. I had looked up the 10.4.12 411 Length Required but don't know why I would be getting it. the code is the example code off the Arduino site and if it is broken I don't have the know how to fix it.

I had similar issues - I ended up using an external library called "ERxPachube.h" from here : Google Code Archive - Long-term storage for Google Code Project Hosting. and their example code works - certainly made the updates easier.

the code is the example code off the Arduino site and if it is broken I don't have the know how to fix it.

This is why I hate pachube and twitter and other sites like that that try to make it seem like any one can, with no programming or networking experience whatsoever, poat anything they want anywhere.

The error message could hardly be more explicit. You must add a client.print() statement that outputs "Content-length: " followed by a client.println() statement that outputs the actual content length. What length is that? Count the number of characters in your data stream. Take your shoes off if necessary.

Thanks poloman, I will give that a try.

The error message could hardly be more explicit. You must add a client.print() statement that outputs "Content-length: " followed by a client.println() statement that outputs the actual content length. What length is that? Count the number of characters in your data stream. Take your shoes off if necessary.

thanks again paul, is that not what the last few lines of code there for? it looks like it should calculate the length or does it need to be inserted manually? This example is in the learning section of the arduino site and that what im trying to do. Thanks!

it looks like it should calculate the length or does it need to be inserted manually?

Well, you're right. It looks like that code is supposed to do that. It's interesting, though, that the error message you posted shows the content type is text/html, when the code defines the content type as text/csv. That leads me to believe that the whole package being sent is not being received.

I wonder if this:

client.print("MY PACHUBE KEY");

needs to be
client.println("MY PACHUBE KEY");

Could be that a missing carriage return/line feed is causing issues.

The content length problem is a common one. A long time ago on the web far away, pachube didn't require the content length. Now it does. Some examples have the content length considered in the code, some don't. Some devices (ethernet shields) do the content length for you and you don't have to bother with it (the now defunct asynclabs wifi shield is one) other shields don't (the arduino 5100 is one of those).

So, don't feel bad that you missed it and are confused because some things do it for you and others don't. Just find a place in the code where you know how long the string you're sending is and count the bytes. Or put it in a string and do a strlen(string) and use that. It's not really hard if you think of it as constructing the data string and then sending it. Just put the length at the top and have at it.

By the way, curl (the command line tool you probably tested with) adds the content length for you so it doesn't even appear there.

Trust me, you CAN make this work. It's just a little confusing.

here's the exact code I use to update pachube so you can compare it:

    strcpy_P(Dbuf,PSTR("PUT /api/9511.csv HTTP/1.1\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Host: www.pachube.com\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("X-PachubeApiKey: bunchOfSecretNumbersGoInHere\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Content-Length: "));
    pachube.print(Dbuf);
    pachube.println(strlen(dataBuf), DEC); // this has to be a println
    strcpy_P(Dbuf,PSTR("Content-Type: text/csv\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Connection: close\n"));
    pachube.println(Dbuf);
    pachube.println(dataBuf);   
    pachube.stop();

I use the rom to store my strings and have the formatted string stored in a thing called dataBuf, so just read the text and look at the prints to get the idea. Been using this for several months without a hiccup.

Sorry for being so slow getting back to this it was my son's wedding last weekend and no time for anything else.

Paul, good catch but I must have deleted the space when i removed my pachube ID code. It wasn't in the original.

Draythomp, thanks for your code I will try and figure out how to use it or see what yours is doing that mine is not.

I have a reply on the pachube site. maybe they can figure out what wrong.

Thanks!

They're really slow in responding to the forum they have. Send them an email, they usually get back in a couple of days. There's only a few worker bees there and they are loaded so be patient.

Also, I changed my code for this yesterday. This is what it looks like now:

    strcpy_P(Dbuf,PSTR("PUT /api/9511.csv HTTP/1.1\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Host: www.pachube.com\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("X-PachubeApiKey: thisisthesecretstuff\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf2,PSTR("Content-Length: %d\n"));
    sprintf(Dbuf,Dbuf2,strlen(dataBuf));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Content-Type: text/csv\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Connection: close\n"));
    pachube.println(Dbuf);
    pachube.println(dataBuf);   
    pachube.stop();

Notice how I handle content length now? You can do the same kind of thing. This actually works much better for me due to some other things I discovered recently about the ethernet board (really long story).