M2X MQTT Client for ARM MBED
Dependents: WNCInterface_M2XMQTTdemo
m2x-mbed.h
00001 #include "mbed.h" 00002 #define USER_AGENT "User-Agent: M2X Mbed MQTT Client/" M2X_VERSION 00003 00004 #ifdef DEBUG 00005 #define DBG(fmt_, data_) printf((fmt_), (data_)) 00006 #define DBGLN(fmt_, data_) printf((fmt_), (data_)); printf("\n") 00007 #define DBGLNEND printf("\n") 00008 #endif /* DEBUG */ 00009 00010 #define F(str) str 00011 00012 class M2XTimer { 00013 public: 00014 void start() { _timer.start(); } 00015 00016 unsigned long read_ms() { 00017 // In case of a timestamp overflow, we reset the server timestamp recorded. 00018 // Notice that unlike Arduino, mbed would overflow every 30 minutes, 00019 // so if 2 calls to this API are more than 30 minutes apart, we are 00020 // likely to run into troubles. This is a limitation of the current 00021 // mbed platform. However, we argue that it might be a rare case that 00022 // 2 calls to this are 30 minutes apart. In most cases, we would call 00023 // this API every few seconds or minutes, this won't be a huge problem. 00024 // However, if you have a use case that would require 2 intervening 00025 // calls to this be 30 minutes apart, you might want to leverage a RTC 00026 // clock instead of the simple ticker here, or call TimeService::reset() 00027 // before making an API call to sync current time. 00028 return _timer.read_ms(); 00029 } 00030 private: 00031 Timer _timer; 00032 }; 00033 00034 #include "TCPSocketConnection.h" 00035 00036 #include <stddef.h> 00037 #include <stdint.h> 00038 #include <stdio.h> 00039 #include <string.h> 00040 00041 #ifdef __cplusplus 00042 extern "C" { 00043 #endif 00044 00045 void delay(int ms) 00046 { 00047 wait_ms(ms); 00048 } 00049 00050 char* strdup(const char* s) 00051 { 00052 char* ret = (char*) malloc(strlen(s) + 1); 00053 if (ret == NULL) { return ret;} 00054 return strcpy(ret, s); 00055 } 00056 00057 #ifdef __cplusplus 00058 } 00059 #endif 00060 00061 class Print { 00062 public: 00063 size_t print(const char* s); 00064 size_t print(char c); 00065 size_t print(int n); 00066 size_t print(long n); 00067 size_t print(double n, int digits = 2); 00068 00069 size_t println(const char* s); 00070 size_t println(char c); 00071 size_t println(int n); 00072 size_t println(long n); 00073 size_t println(double n, int digits = 2); 00074 size_t println(); 00075 00076 virtual size_t write(uint8_t c) = 0; 00077 virtual size_t write(const uint8_t* buf, size_t size); 00078 }; 00079 00080 size_t Print::write(const uint8_t* buf, size_t size) { 00081 size_t ret = 0; 00082 while (size--) { 00083 ret += write(*buf++); 00084 } 00085 return ret; 00086 } 00087 00088 size_t Print::print(const char* s) { 00089 return write((const uint8_t*)s, strlen(s)); 00090 } 00091 00092 size_t Print::print(char c) { 00093 return write(c); 00094 } 00095 00096 size_t Print::print(int n) { 00097 return print((long) n); 00098 } 00099 00100 size_t Print::print(long n) { 00101 char buf[8 * sizeof(long) + 1]; 00102 snprintf(buf, sizeof(buf), "%ld", n); 00103 return print(buf); 00104 } 00105 00106 // Digits are ignored for now 00107 size_t Print::print(double n, int digits) { 00108 char buf[65]; 00109 snprintf(buf, sizeof(buf), "%g", n); 00110 return print(buf); 00111 } 00112 00113 size_t Print::println(const char* s) { 00114 return print(s) + println(); 00115 } 00116 00117 size_t Print::println(char c) { 00118 return print(c) + println(); 00119 } 00120 00121 size_t Print::println(int n) { 00122 return print(n) + println(); 00123 } 00124 00125 size_t Print::println(long n) { 00126 return print(n) + println(); 00127 } 00128 00129 size_t Print::println(double n, int digits) { 00130 return print(n, digits) + println(); 00131 } 00132 00133 size_t Print::println() { 00134 return print('\r') + print('\n'); 00135 } 00136 00137 /* 00138 * TCP Client 00139 */ 00140 class Client : public Print { 00141 public: 00142 Client(); 00143 ~Client(); 00144 00145 virtual int connect(const char *host, uint16_t port); 00146 virtual size_t write(uint8_t); 00147 virtual size_t write(const uint8_t *buf, size_t size); 00148 virtual int available(); 00149 virtual int read(); 00150 virtual void flush(); 00151 virtual void stop(); 00152 virtual uint8_t connected(); 00153 private: 00154 virtual int read(uint8_t *buf, size_t size); 00155 void _fillin(void); 00156 uint8_t _inbuf[128]; 00157 uint8_t _incnt; 00158 void _flushout(void); 00159 uint8_t _outbuf[128]; 00160 uint8_t _outcnt; 00161 TCPSocketConnection _sock; 00162 }; 00163 00164 Client::Client() : _incnt(0), _outcnt(0), _sock() { 00165 _sock.set_blocking(false, 1500); 00166 } 00167 00168 Client::~Client() { 00169 } 00170 00171 int Client::connect(const char *host, uint16_t port) { 00172 return _sock.connect(host, port) == 0; 00173 } 00174 00175 size_t Client::write(uint8_t b) { 00176 return write(&b, 1); 00177 } 00178 00179 size_t Client::write(const uint8_t *buf, size_t size) { 00180 size_t cnt = 0; 00181 while (size) { 00182 int tmp = sizeof(_outbuf) - _outcnt; 00183 if (tmp > size) tmp = size; 00184 memcpy(_outbuf + _outcnt, buf, tmp); 00185 _outcnt += tmp; 00186 buf += tmp; 00187 size -= tmp; 00188 cnt += tmp; 00189 // if no space flush it 00190 if (_outcnt == sizeof(_outbuf)) 00191 _flushout(); 00192 } 00193 return cnt; 00194 } 00195 00196 void Client::_flushout(void) 00197 { 00198 if (_outcnt > 0) { 00199 // NOTE: we know it's dangerous to cast from (const uint8_t *) to (char *), 00200 // but we are trying to maintain a stable interface between the Arduino 00201 // one and the mbed one. What's more, while TCPSocketConnection has no 00202 // intention of modifying the data here, it requires us to send a (char *) 00203 // typed data. So we belive it's safe to do the cast here. 00204 _sock.send_all(const_cast<char*>((const char*) _outbuf), _outcnt); 00205 _outcnt = 0; 00206 } 00207 } 00208 00209 void Client::_fillin(void) 00210 { 00211 int tmp = sizeof(_inbuf) - _incnt; 00212 if (tmp) { 00213 tmp = _sock.receive_all((char*)_inbuf + _incnt, tmp); 00214 if (tmp > 0) 00215 _incnt += tmp; 00216 } 00217 } 00218 00219 void Client::flush() { 00220 _flushout(); 00221 } 00222 00223 int Client::available() { 00224 if (_incnt == 0) { 00225 _flushout(); 00226 _fillin(); 00227 } 00228 return (_incnt > 0) ? 1 : 0; 00229 } 00230 00231 int Client::read() { 00232 uint8_t ch; 00233 return (read(&ch, 1) == 1) ? ch : -1; 00234 } 00235 00236 int Client::read(uint8_t *buf, size_t size) { 00237 int cnt = 0; 00238 while (size) { 00239 // need more 00240 if (size > _incnt) { 00241 _flushout(); 00242 _fillin(); 00243 } 00244 if (_incnt > 0) { 00245 int tmp = _incnt; 00246 if (tmp > size) tmp = size; 00247 memcpy(buf, _inbuf, tmp); 00248 if (tmp != _incnt) 00249 memmove(_inbuf, _inbuf + tmp, _incnt - tmp); 00250 _incnt -= tmp; 00251 size -= tmp; 00252 buf += tmp; 00253 cnt += tmp; 00254 } else // no data 00255 break; 00256 } 00257 return cnt; 00258 } 00259 00260 void Client::stop() { 00261 _sock.close(); 00262 } 00263 00264 uint8_t Client::connected() { 00265 return _sock.is_connected() ? 1 : 0; 00266 }
Generated on Sun Aug 7 2022 04:57:39 by 1.7.2