ARM mbed M2X API Client: The ARM mbed client library is used to send/receive data to/from AT&T's M2X service from mbed LPC1768 microcontrollers.

Dependents:   m2x-demo-all M2X_MTS_ACCEL_DEMO M2X_MTS_Accel M2X_K64F_ACCEL ... more

Committer:
defmacro
Date:
Wed Jun 15 12:36:55 2016 +0000
Revision:
22:4d895e732765
Update to new single header based implementation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
defmacro 22:4d895e732765 1 #include "mbed.h"
defmacro 22:4d895e732765 2 #define USER_AGENT "User-Agent: M2X Mbed Client/" M2X_VERSION
defmacro 22:4d895e732765 3
defmacro 22:4d895e732765 4 #ifdef DEBUG
defmacro 22:4d895e732765 5 #define DBG(fmt_, data_) printf((fmt_), (data_))
defmacro 22:4d895e732765 6 #define DBGLN(fmt_, data_) printf((fmt_), (data_)); printf("\n")
defmacro 22:4d895e732765 7 #define DBGLNEND printf("\n")
defmacro 22:4d895e732765 8 #endif /* DEBUG */
defmacro 22:4d895e732765 9
defmacro 22:4d895e732765 10 class M2XTimer {
defmacro 22:4d895e732765 11 public:
defmacro 22:4d895e732765 12 void start() { _timer.start(); }
defmacro 22:4d895e732765 13
defmacro 22:4d895e732765 14 unsigned long read_ms() {
defmacro 22:4d895e732765 15 // In case of a timestamp overflow, we reset the server timestamp recorded.
defmacro 22:4d895e732765 16 // Notice that unlike Arduino, mbed would overflow every 30 minutes,
defmacro 22:4d895e732765 17 // so if 2 calls to this API are more than 30 minutes apart, we are
defmacro 22:4d895e732765 18 // likely to run into troubles. This is a limitation of the current
defmacro 22:4d895e732765 19 // mbed platform. However, we argue that it might be a rare case that
defmacro 22:4d895e732765 20 // 2 calls to this are 30 minutes apart. In most cases, we would call
defmacro 22:4d895e732765 21 // this API every few seconds or minutes, this won't be a huge problem.
defmacro 22:4d895e732765 22 // However, if you have a use case that would require 2 intervening
defmacro 22:4d895e732765 23 // calls to this be 30 minutes apart, you might want to leverage a RTC
defmacro 22:4d895e732765 24 // clock instead of the simple ticker here, or call TimeService::reset()
defmacro 22:4d895e732765 25 // before making an API call to sync current time.
defmacro 22:4d895e732765 26 return _timer.read_ms();
defmacro 22:4d895e732765 27 }
defmacro 22:4d895e732765 28 private:
defmacro 22:4d895e732765 29 Timer _timer;
defmacro 22:4d895e732765 30 };
defmacro 22:4d895e732765 31
defmacro 22:4d895e732765 32 #include "TCPSocketConnection.h"
defmacro 22:4d895e732765 33
defmacro 22:4d895e732765 34 #include <stddef.h>
defmacro 22:4d895e732765 35 #include <stdint.h>
defmacro 22:4d895e732765 36 #include <stdio.h>
defmacro 22:4d895e732765 37 #include <string.h>
defmacro 22:4d895e732765 38
defmacro 22:4d895e732765 39 #ifdef __cplusplus
defmacro 22:4d895e732765 40 extern "C" {
defmacro 22:4d895e732765 41 #endif
defmacro 22:4d895e732765 42
defmacro 22:4d895e732765 43 void delay(int ms)
defmacro 22:4d895e732765 44 {
defmacro 22:4d895e732765 45 wait_ms(ms);
defmacro 22:4d895e732765 46 }
defmacro 22:4d895e732765 47
defmacro 22:4d895e732765 48 char* strdup(const char* s)
defmacro 22:4d895e732765 49 {
defmacro 22:4d895e732765 50 char* ret = (char*) malloc(strlen(s) + 1);
defmacro 22:4d895e732765 51 if (ret == NULL) { return ret;}
defmacro 22:4d895e732765 52 return strcpy(ret, s);
defmacro 22:4d895e732765 53 }
defmacro 22:4d895e732765 54
defmacro 22:4d895e732765 55 #ifdef __cplusplus
defmacro 22:4d895e732765 56 }
defmacro 22:4d895e732765 57 #endif
defmacro 22:4d895e732765 58
defmacro 22:4d895e732765 59 class Print {
defmacro 22:4d895e732765 60 public:
defmacro 22:4d895e732765 61 size_t print(const char* s);
defmacro 22:4d895e732765 62 size_t print(char c);
defmacro 22:4d895e732765 63 size_t print(int n);
defmacro 22:4d895e732765 64 size_t print(long n);
defmacro 22:4d895e732765 65 size_t print(double n, int digits = 2);
defmacro 22:4d895e732765 66
defmacro 22:4d895e732765 67 size_t println(const char* s);
defmacro 22:4d895e732765 68 size_t println(char c);
defmacro 22:4d895e732765 69 size_t println(int n);
defmacro 22:4d895e732765 70 size_t println(long n);
defmacro 22:4d895e732765 71 size_t println(double n, int digits = 2);
defmacro 22:4d895e732765 72 size_t println();
defmacro 22:4d895e732765 73
defmacro 22:4d895e732765 74 virtual size_t write(uint8_t c) = 0;
defmacro 22:4d895e732765 75 virtual size_t write(const uint8_t* buf, size_t size);
defmacro 22:4d895e732765 76 };
defmacro 22:4d895e732765 77
defmacro 22:4d895e732765 78 size_t Print::write(const uint8_t* buf, size_t size) {
defmacro 22:4d895e732765 79 size_t ret = 0;
defmacro 22:4d895e732765 80 while (size--) {
defmacro 22:4d895e732765 81 ret += write(*buf++);
defmacro 22:4d895e732765 82 }
defmacro 22:4d895e732765 83 return ret;
defmacro 22:4d895e732765 84 }
defmacro 22:4d895e732765 85
defmacro 22:4d895e732765 86 size_t Print::print(const char* s) {
defmacro 22:4d895e732765 87 return write((const uint8_t*)s, strlen(s));
defmacro 22:4d895e732765 88 }
defmacro 22:4d895e732765 89
defmacro 22:4d895e732765 90 size_t Print::print(char c) {
defmacro 22:4d895e732765 91 return write(c);
defmacro 22:4d895e732765 92 }
defmacro 22:4d895e732765 93
defmacro 22:4d895e732765 94 size_t Print::print(int n) {
defmacro 22:4d895e732765 95 return print((long) n);
defmacro 22:4d895e732765 96 }
defmacro 22:4d895e732765 97
defmacro 22:4d895e732765 98 size_t Print::print(long n) {
defmacro 22:4d895e732765 99 char buf[8 * sizeof(long) + 1];
defmacro 22:4d895e732765 100 snprintf(buf, sizeof(buf), "%ld", n);
defmacro 22:4d895e732765 101 return print(buf);
defmacro 22:4d895e732765 102 }
defmacro 22:4d895e732765 103
defmacro 22:4d895e732765 104 // Digits are ignored for now
defmacro 22:4d895e732765 105 size_t Print::print(double n, int digits) {
defmacro 22:4d895e732765 106 char buf[65];
defmacro 22:4d895e732765 107 snprintf(buf, sizeof(buf), "%g", n);
defmacro 22:4d895e732765 108 return print(buf);
defmacro 22:4d895e732765 109 }
defmacro 22:4d895e732765 110
defmacro 22:4d895e732765 111 size_t Print::println(const char* s) {
defmacro 22:4d895e732765 112 return print(s) + println();
defmacro 22:4d895e732765 113 }
defmacro 22:4d895e732765 114
defmacro 22:4d895e732765 115 size_t Print::println(char c) {
defmacro 22:4d895e732765 116 return print(c) + println();
defmacro 22:4d895e732765 117 }
defmacro 22:4d895e732765 118
defmacro 22:4d895e732765 119 size_t Print::println(int n) {
defmacro 22:4d895e732765 120 return print(n) + println();
defmacro 22:4d895e732765 121 }
defmacro 22:4d895e732765 122
defmacro 22:4d895e732765 123 size_t Print::println(long n) {
defmacro 22:4d895e732765 124 return print(n) + println();
defmacro 22:4d895e732765 125 }
defmacro 22:4d895e732765 126
defmacro 22:4d895e732765 127 size_t Print::println(double n, int digits) {
defmacro 22:4d895e732765 128 return print(n, digits) + println();
defmacro 22:4d895e732765 129 }
defmacro 22:4d895e732765 130
defmacro 22:4d895e732765 131 size_t Print::println() {
defmacro 22:4d895e732765 132 return print('\r') + print('\n');
defmacro 22:4d895e732765 133 }
defmacro 22:4d895e732765 134
defmacro 22:4d895e732765 135 /*
defmacro 22:4d895e732765 136 * TCP Client
defmacro 22:4d895e732765 137 */
defmacro 22:4d895e732765 138 class Client : public Print {
defmacro 22:4d895e732765 139 public:
defmacro 22:4d895e732765 140 Client();
defmacro 22:4d895e732765 141 ~Client();
defmacro 22:4d895e732765 142
defmacro 22:4d895e732765 143 virtual int connect(const char *host, uint16_t port);
defmacro 22:4d895e732765 144 virtual size_t write(uint8_t);
defmacro 22:4d895e732765 145 virtual size_t write(const uint8_t *buf, size_t size);
defmacro 22:4d895e732765 146 virtual int available();
defmacro 22:4d895e732765 147 virtual int read();
defmacro 22:4d895e732765 148 virtual void flush();
defmacro 22:4d895e732765 149 virtual void stop();
defmacro 22:4d895e732765 150 virtual uint8_t connected();
defmacro 22:4d895e732765 151 private:
defmacro 22:4d895e732765 152 virtual int read(uint8_t *buf, size_t size);
defmacro 22:4d895e732765 153 void _fillin(void);
defmacro 22:4d895e732765 154 uint8_t _inbuf[128];
defmacro 22:4d895e732765 155 uint8_t _incnt;
defmacro 22:4d895e732765 156 void _flushout(void);
defmacro 22:4d895e732765 157 uint8_t _outbuf[128];
defmacro 22:4d895e732765 158 uint8_t _outcnt;
defmacro 22:4d895e732765 159 TCPSocketConnection _sock;
defmacro 22:4d895e732765 160 };
defmacro 22:4d895e732765 161
defmacro 22:4d895e732765 162 Client::Client() : _incnt(0), _outcnt(0), _sock() {
defmacro 22:4d895e732765 163 _sock.set_blocking(false, 1500);
defmacro 22:4d895e732765 164 }
defmacro 22:4d895e732765 165
defmacro 22:4d895e732765 166 Client::~Client() {
defmacro 22:4d895e732765 167 }
defmacro 22:4d895e732765 168
defmacro 22:4d895e732765 169 int Client::connect(const char *host, uint16_t port) {
defmacro 22:4d895e732765 170 return _sock.connect(host, port) == 0;
defmacro 22:4d895e732765 171 }
defmacro 22:4d895e732765 172
defmacro 22:4d895e732765 173 size_t Client::write(uint8_t b) {
defmacro 22:4d895e732765 174 return write(&b, 1);
defmacro 22:4d895e732765 175 }
defmacro 22:4d895e732765 176
defmacro 22:4d895e732765 177 size_t Client::write(const uint8_t *buf, size_t size) {
defmacro 22:4d895e732765 178 size_t cnt = 0;
defmacro 22:4d895e732765 179 while (size) {
defmacro 22:4d895e732765 180 int tmp = sizeof(_outbuf) - _outcnt;
defmacro 22:4d895e732765 181 if (tmp > size) tmp = size;
defmacro 22:4d895e732765 182 memcpy(_outbuf + _outcnt, buf, tmp);
defmacro 22:4d895e732765 183 _outcnt += tmp;
defmacro 22:4d895e732765 184 buf += tmp;
defmacro 22:4d895e732765 185 size -= tmp;
defmacro 22:4d895e732765 186 cnt += tmp;
defmacro 22:4d895e732765 187 // if no space flush it
defmacro 22:4d895e732765 188 if (_outcnt == sizeof(_outbuf))
defmacro 22:4d895e732765 189 _flushout();
defmacro 22:4d895e732765 190 }
defmacro 22:4d895e732765 191 return cnt;
defmacro 22:4d895e732765 192 }
defmacro 22:4d895e732765 193
defmacro 22:4d895e732765 194 void Client::_flushout(void)
defmacro 22:4d895e732765 195 {
defmacro 22:4d895e732765 196 if (_outcnt > 0) {
defmacro 22:4d895e732765 197 // NOTE: we know it's dangerous to cast from (const uint8_t *) to (char *),
defmacro 22:4d895e732765 198 // but we are trying to maintain a stable interface between the Arduino
defmacro 22:4d895e732765 199 // one and the mbed one. What's more, while TCPSocketConnection has no
defmacro 22:4d895e732765 200 // intention of modifying the data here, it requires us to send a (char *)
defmacro 22:4d895e732765 201 // typed data. So we belive it's safe to do the cast here.
defmacro 22:4d895e732765 202 _sock.send_all(const_cast<char*>((const char*) _outbuf), _outcnt);
defmacro 22:4d895e732765 203 _outcnt = 0;
defmacro 22:4d895e732765 204 }
defmacro 22:4d895e732765 205 }
defmacro 22:4d895e732765 206
defmacro 22:4d895e732765 207 void Client::_fillin(void)
defmacro 22:4d895e732765 208 {
defmacro 22:4d895e732765 209 int tmp = sizeof(_inbuf) - _incnt;
defmacro 22:4d895e732765 210 if (tmp) {
defmacro 22:4d895e732765 211 tmp = _sock.receive_all((char*)_inbuf + _incnt, tmp);
defmacro 22:4d895e732765 212 if (tmp > 0)
defmacro 22:4d895e732765 213 _incnt += tmp;
defmacro 22:4d895e732765 214 }
defmacro 22:4d895e732765 215 }
defmacro 22:4d895e732765 216
defmacro 22:4d895e732765 217 void Client::flush() {
defmacro 22:4d895e732765 218 _flushout();
defmacro 22:4d895e732765 219 }
defmacro 22:4d895e732765 220
defmacro 22:4d895e732765 221 int Client::available() {
defmacro 22:4d895e732765 222 if (_incnt == 0) {
defmacro 22:4d895e732765 223 _flushout();
defmacro 22:4d895e732765 224 _fillin();
defmacro 22:4d895e732765 225 }
defmacro 22:4d895e732765 226 return (_incnt > 0) ? 1 : 0;
defmacro 22:4d895e732765 227 }
defmacro 22:4d895e732765 228
defmacro 22:4d895e732765 229 int Client::read() {
defmacro 22:4d895e732765 230 uint8_t ch;
defmacro 22:4d895e732765 231 return (read(&ch, 1) == 1) ? ch : -1;
defmacro 22:4d895e732765 232 }
defmacro 22:4d895e732765 233
defmacro 22:4d895e732765 234 int Client::read(uint8_t *buf, size_t size) {
defmacro 22:4d895e732765 235 int cnt = 0;
defmacro 22:4d895e732765 236 while (size) {
defmacro 22:4d895e732765 237 // need more
defmacro 22:4d895e732765 238 if (size > _incnt) {
defmacro 22:4d895e732765 239 _flushout();
defmacro 22:4d895e732765 240 _fillin();
defmacro 22:4d895e732765 241 }
defmacro 22:4d895e732765 242 if (_incnt > 0) {
defmacro 22:4d895e732765 243 int tmp = _incnt;
defmacro 22:4d895e732765 244 if (tmp > size) tmp = size;
defmacro 22:4d895e732765 245 memcpy(buf, _inbuf, tmp);
defmacro 22:4d895e732765 246 if (tmp != _incnt)
defmacro 22:4d895e732765 247 memmove(_inbuf, _inbuf + tmp, _incnt - tmp);
defmacro 22:4d895e732765 248 _incnt -= tmp;
defmacro 22:4d895e732765 249 size -= tmp;
defmacro 22:4d895e732765 250 buf += tmp;
defmacro 22:4d895e732765 251 cnt += tmp;
defmacro 22:4d895e732765 252 } else // no data
defmacro 22:4d895e732765 253 break;
defmacro 22:4d895e732765 254 }
defmacro 22:4d895e732765 255 return cnt;
defmacro 22:4d895e732765 256 }
defmacro 22:4d895e732765 257
defmacro 22:4d895e732765 258 void Client::stop() {
defmacro 22:4d895e732765 259 _sock.close();
defmacro 22:4d895e732765 260 }
defmacro 22:4d895e732765 261
defmacro 22:4d895e732765 262 uint8_t Client::connected() {
defmacro 22:4d895e732765 263 return _sock.is_connected() ? 1 : 0;
defmacro 22:4d895e732765 264 }