2 #include <HttpClient.h>
3 #include <CountingStream.h>
5 XivelyClient::XivelyClient(Client& aClient)
10 int XivelyClient::put(XivelyFeed& aFeed, const char* aApiKey)
12 HttpClient http(_client);
14 buildPath(path, aFeed.id(), "json");
16 int ret = http.put("api.xively.com", path);
19 http.sendHeader("X-ApiKey", aApiKey);
20 http.sendHeader("User-Agent", "Xively-Arduino-Lib/1.0");
22 CountingStream countingStream; // Used to work out how long that data will be
23 for (int i =kCalculateDataLength; i <= kSendData; i++)
27 if (i == kCalculateDataLength)
35 len = s->print(aFeed);
36 if (i == kCalculateDataLength)
38 // We now know how long the data will be...
39 http.sendHeader("Content-Length", len);
42 // Now we're done sending the request
45 ret = http.responseStatusCode();
46 if ((ret < 200) || (ret > 299))
48 // It wasn't a successful response, ensure it's -ve so the error is easy to spot
60 void XivelyClient::buildPath(char* aDest, unsigned long aFeedId, const char* aFormat)
63 strcpy(aDest, "/v2/feeds/");
66 for(*p--=aFeedId%10+0x30;aFeedId/=10;*p--=aFeedId%10+0x30);
69 strcat(aDest, aFormat);
72 int XivelyClient::get(XivelyFeed& aFeed, const char* aApiKey)
74 HttpClient http(_client);
76 buildPath(path, aFeed.id(), "csv");
78 int ret = http.get("api.xively.com", path);
81 http.sendHeader("X-ApiKey", aApiKey);
82 http.sendHeader("User-Agent", "Xively-Arduino-Lib/1.0");
85 ret = http.responseStatusCode();
86 if ((ret < 200) || (ret > 299))
88 // It wasn't a successful response, ensure it's -ve so the error is easy to spot
96 http.skipResponseHeaders();
97 // Now we need to run through each line, looking to see if it matches one
98 // of the given datastreams.
99 // So that we don't use any more memory than necessary, we'll keep track
100 // of which character we're up to in the ID string, and have a bit-field
101 // of the remaining datastreams that match. This limits us (if we use
102 // and unsigned long) to 32 datastreams in a feed, but that's probably ok
104 unsigned long idBitfield = 0;
105 for (int i =0; i < aFeed.size(); i++)
107 idBitfield |= 1 << i;
109 // As long as we've got bitfields to read
110 // FIXME Need to time out if this hangs for too long
111 while ((http.available() || http.connected()))
113 if (http.available())
115 char next = http.read();
119 // We've reached the end of the ID string, see if it matches any of the
120 // datastreams in the feed
121 // But first skip the updated time, to get to the value
123 for (int i =0; i < aFeed.size(); i++)
125 if ((idBitfield & 1<<i) && (aFeed[i].idLength() == idIdx))
127 // We've found a matching datastream
128 // FIXME cope with any errors returned
129 aFeed[i].updateValue(http);
130 // When we get here we'll be at the end of the line, but if aFeed[i]
131 // was a string or buffer type, we'll have consumed the '\n'
135 // Need to run to the end of the line regardless now
136 // And deliberately drop through into the next case
137 while ((next != '\r') && (next != '\n') && (http.available() || http.connected()))
143 // We've hit the end of the line, reset everything
145 for (int i =0; i < aFeed.size(); i++)
147 idBitfield |= 1 << i;
151 // Next character of the ID string
152 for (int i =0; i < aFeed.size(); i++)
154 if (!(idBitfield & 1<<i) || (aFeed[i].idChar(idIdx) != next))
156 idBitfield &= ~(1<<i);
158 // else we're still matching
160 idIdx++; // onto the next character in the ID