Simplify using of UnbufferedSerial(Serial), USBCDC, TCP, SMTP, NTP Fork : https://github.com/YSI-LPS/lib_Transmission

Dependents:   lib_Transmission_Serial_example 2022_TICE_Electrolyse lib_Transmission_TCP_example

Committer:
YSI
Date:
Wed Jun 09 13:54:28 2021 +0000
Revision:
20:2672d4aea6b7
Parent:
19:6c5777719ece
Child:
21:59c0adcdfe9b
tcp recv change and fix 100ms timeout

Who changed what in which revision?

UserRevisionLine numberNew contents of line
YSI 0:2fc6fc3b5e15 1 #include "lib_Transmission.h"
YSI 20:2672d4aea6b7 2 #include <sstream>
YSI 18:15778c8a97a1 3
YSI 18:15778c8a97a1 4 Transmission::Transmission(
YSI 18:15778c8a97a1 5 #if MBED_MAJOR_VERSION > 5
YSI 18:15778c8a97a1 6 UnbufferedSerial *serial,
YSI 18:15778c8a97a1 7 #else
YSI 18:15778c8a97a1 8 Serial *serial,
YSI 18:15778c8a97a1 9 #endif
YSI 18:15778c8a97a1 10 USBCDC *usb,
YSI 18:15778c8a97a1 11 EthernetInterface *eth,
YSI 18:15778c8a97a1 12 string (*processing)(string),
YSI 18:15778c8a97a1 13 void (*ethup)(void),
YSI 18:15778c8a97a1 14 bool caseIgnore)
YSI 18:15778c8a97a1 15 :_serial(serial), _usb(usb), _eth(eth), _processing(processing), _ethup(ethup), _caseIgnore(caseIgnore)
YSI 18:15778c8a97a1 16 {
YSI 18:15778c8a97a1 17 if(_serial) _serial->attach(callback(this, &Transmission::serial_event));
YSI 18:15778c8a97a1 18 _queue = mbed_event_queue();
YSI 18:15778c8a97a1 19 }
YSI 18:15778c8a97a1 20
YSI 18:15778c8a97a1 21 Transmission::Transmission(
YSI 18:15778c8a97a1 22 #if MBED_MAJOR_VERSION > 5
YSI 18:15778c8a97a1 23 UnbufferedSerial *serial,
YSI 18:15778c8a97a1 24 #else
YSI 18:15778c8a97a1 25 Serial *serial,
YSI 18:15778c8a97a1 26 #endif
YSI 18:15778c8a97a1 27 USBCDC *usb,
YSI 18:15778c8a97a1 28 string (*processing)(string),
YSI 18:15778c8a97a1 29 bool caseIgnore)
YSI 18:15778c8a97a1 30 :_serial(serial), _usb(usb), _processing(processing), _caseIgnore(caseIgnore)
YSI 18:15778c8a97a1 31 {
YSI 18:15778c8a97a1 32 if(_serial) _serial->attach(callback(this, &Transmission::serial_event));
YSI 18:15778c8a97a1 33 _queue = mbed_event_queue();
YSI 18:15778c8a97a1 34 }
YSI 0:2fc6fc3b5e15 35
YSI 14:9e3accc681c4 36 Transmission::Transmission(
YSI 14:9e3accc681c4 37 #if MBED_MAJOR_VERSION > 5
YSI 15:b2da6ab01a21 38 UnbufferedSerial *serial,
YSI 14:9e3accc681c4 39 #else
YSI 15:b2da6ab01a21 40 Serial *serial,
YSI 14:9e3accc681c4 41 #endif
YSI 15:b2da6ab01a21 42 EthernetInterface *eth,
YSI 15:b2da6ab01a21 43 string (*processing)(string),
YSI 18:15778c8a97a1 44 void (*ethup)(void),
YSI 15:b2da6ab01a21 45 bool caseIgnore)
YSI 18:15778c8a97a1 46 :_serial(serial), _eth(eth), _processing(processing), _ethup(ethup), _caseIgnore(caseIgnore)
YSI 0:2fc6fc3b5e15 47 {
YSI 16:3ef69ffede76 48 if(_serial) _serial->attach(callback(this, &Transmission::serial_event));
YSI 14:9e3accc681c4 49 _queue = mbed_event_queue();
YSI 0:2fc6fc3b5e15 50 }
YSI 0:2fc6fc3b5e15 51
YSI 15:b2da6ab01a21 52 Transmission::Transmission(
YSI 18:15778c8a97a1 53 USBCDC *usb,
YSI 18:15778c8a97a1 54 EthernetInterface *eth,
YSI 18:15778c8a97a1 55 string (*processing)(string),
YSI 18:15778c8a97a1 56 void (*ethup)(void),
YSI 18:15778c8a97a1 57 bool caseIgnore)
YSI 18:15778c8a97a1 58 :_usb(usb), _eth(eth), _processing(processing), _ethup(ethup), _caseIgnore(caseIgnore)
YSI 18:15778c8a97a1 59 {
YSI 18:15778c8a97a1 60 _queue = mbed_event_queue();
YSI 18:15778c8a97a1 61 }
YSI 18:15778c8a97a1 62
YSI 18:15778c8a97a1 63 Transmission::Transmission(
YSI 15:b2da6ab01a21 64 #if MBED_MAJOR_VERSION > 5
YSI 15:b2da6ab01a21 65 UnbufferedSerial *serial,
YSI 15:b2da6ab01a21 66 #else
YSI 15:b2da6ab01a21 67 Serial *serial,
YSI 15:b2da6ab01a21 68 #endif
YSI 15:b2da6ab01a21 69 string (*processing)(string),
YSI 15:b2da6ab01a21 70 bool caseIgnore)
YSI 15:b2da6ab01a21 71 :_serial(serial), _processing(processing), _caseIgnore(caseIgnore)
YSI 15:b2da6ab01a21 72 {
YSI 16:3ef69ffede76 73 if(_serial) _serial->attach(callback(this, &Transmission::serial_event));
YSI 15:b2da6ab01a21 74 _queue = mbed_event_queue();
YSI 15:b2da6ab01a21 75 }
YSI 15:b2da6ab01a21 76
YSI 15:b2da6ab01a21 77 Transmission::Transmission(
YSI 15:b2da6ab01a21 78 EthernetInterface *eth,
YSI 15:b2da6ab01a21 79 string (*processing)(string),
YSI 18:15778c8a97a1 80 void (*ethup)(void),
YSI 15:b2da6ab01a21 81 bool caseIgnore)
YSI 18:15778c8a97a1 82 :_eth(eth), _processing(processing), _ethup(ethup), _caseIgnore(caseIgnore)
YSI 15:b2da6ab01a21 83 {
YSI 15:b2da6ab01a21 84 _queue = mbed_event_queue();
YSI 15:b2da6ab01a21 85 }
YSI 15:b2da6ab01a21 86
YSI 15:b2da6ab01a21 87 Transmission::Transmission(
YSI 15:b2da6ab01a21 88 USBCDC *usb,
YSI 15:b2da6ab01a21 89 string (*processing)(string),
YSI 15:b2da6ab01a21 90 bool caseIgnore)
YSI 18:15778c8a97a1 91 :_usb(usb), _processing(processing), _caseIgnore(caseIgnore)
YSI 18:15778c8a97a1 92 {}
YSI 15:b2da6ab01a21 93
YSI 14:9e3accc681c4 94 string Transmission::ip(const bool& SET, const char* IP, const uint16_t& PORT, const uint16_t& TIMEOUT)
YSI 3:7e15bf0a71f4 95 {
YSI 16:3ef69ffede76 96 if(!_eth) return "00:00:00:00:00:00";
YSI 10:25e049353db5 97 if(message.SET && SET)
YSI 3:7e15bf0a71f4 98 {
YSI 3:7e15bf0a71f4 99 if(message.PORT != PORT)
YSI 3:7e15bf0a71f4 100 {
YSI 3:7e15bf0a71f4 101 message.CONNECT = false;
YSI 3:7e15bf0a71f4 102 _serverTCP.sigio(NULL);
YSI 3:7e15bf0a71f4 103 eth_error("serverTCP_close", _serverTCP.close());
YSI 3:7e15bf0a71f4 104 }
YSI 3:7e15bf0a71f4 105 eth_error("Ethernet_disconnect", _eth->disconnect());
YSI 3:7e15bf0a71f4 106 }
YSI 10:25e049353db5 107 message.SET = SET;
YSI 3:7e15bf0a71f4 108 message.IP = IP;
YSI 3:7e15bf0a71f4 109 message.PORT = PORT;
YSI 14:9e3accc681c4 110 message.TIMEOUT = TIMEOUT;
YSI 3:7e15bf0a71f4 111 message.DHCP = message.IP.empty();
YSI 10:25e049353db5 112 eth_connect();
YSI 14:9e3accc681c4 113 return _eth->get_mac_address()?_eth->get_mac_address():"00:00:00:00:00:00";
YSI 3:7e15bf0a71f4 114 }
YSI 3:7e15bf0a71f4 115
YSI 14:9e3accc681c4 116 string Transmission::ip(void)
YSI 3:7e15bf0a71f4 117 {
YSI 16:3ef69ffede76 118 if(!_eth) return "0.0.0.0";
YSI 3:7e15bf0a71f4 119 SocketAddress ip;
YSI 3:7e15bf0a71f4 120 _eth->get_ip_address(&ip);
YSI 3:7e15bf0a71f4 121 string address(ip.get_ip_address()?ip.get_ip_address():"0.0.0.0");
YSI 3:7e15bf0a71f4 122 address += ":" + to_string(message.PORT);
YSI 3:7e15bf0a71f4 123 return address;
YSI 3:7e15bf0a71f4 124 }
YSI 3:7e15bf0a71f4 125
YSI 0:2fc6fc3b5e15 126 bool Transmission::eth_connect(void)
YSI 0:2fc6fc3b5e15 127 {
YSI 16:3ef69ffede76 128 if(!_eth) return false;
YSI 10:25e049353db5 129 if(message.SET)
YSI 0:2fc6fc3b5e15 130 {
YSI 0:2fc6fc3b5e15 131 switch(_eth->get_connection_status())
YSI 0:2fc6fc3b5e15 132 {
YSI 0:2fc6fc3b5e15 133 case NSAPI_STATUS_DISCONNECTED:
YSI 14:9e3accc681c4 134 eth_error("Ethernet_blocking", _eth->set_blocking(false));
YSI 14:9e3accc681c4 135 eth_error("Ethernet_dhcp", _eth->set_dhcp(message.DHCP));
YSI 14:9e3accc681c4 136 if(!message.DHCP) eth_error("Ethernet_static", _eth->set_network(SocketAddress(message.IP.c_str()), SocketAddress("255.255.255.0"), SocketAddress("192.168.1.1")));
YSI 14:9e3accc681c4 137 _eth->attach(callback(this, &Transmission::eth_event));
YSI 15:b2da6ab01a21 138 eth_error("Ethernet_connect", _eth->connect()); break;
YSI 14:9e3accc681c4 139 case NSAPI_STATUS_GLOBAL_UP: return message.CONNECT;break;
YSI 14:9e3accc681c4 140 default: break;
YSI 0:2fc6fc3b5e15 141 }
YSI 0:2fc6fc3b5e15 142 }
YSI 0:2fc6fc3b5e15 143 else if(_eth->get_connection_status() != NSAPI_STATUS_DISCONNECTED) eth_error("Ethernet_disconnect", _eth->disconnect());
YSI 0:2fc6fc3b5e15 144 return false;
YSI 0:2fc6fc3b5e15 145 }
YSI 0:2fc6fc3b5e15 146
YSI 0:2fc6fc3b5e15 147 void Transmission::eth_event(nsapi_event_t status, intptr_t param)
YSI 0:2fc6fc3b5e15 148 {
YSI 0:2fc6fc3b5e15 149 eth_status("Ethernet_event", param);
YSI 0:2fc6fc3b5e15 150 switch(param)
YSI 0:2fc6fc3b5e15 151 {
YSI 15:b2da6ab01a21 152 case NSAPI_STATUS_DISCONNECTED: message.status = RED_DISCONNECTED; break;
YSI 4:9a4ab4f406ab 153 case NSAPI_STATUS_CONNECTING:if(message.status == BLUE_CLIENT) eth_error("clientTCP_disconnect", _clientTCP->close());
YSI 15:b2da6ab01a21 154 message.status = YELLOW_CONNECTING; break;
YSI 3:7e15bf0a71f4 155 case NSAPI_STATUS_GLOBAL_UP: message.status = GREEN_GLOBAL_UP;
YSI 15:b2da6ab01a21 156 if(!message.CONNECT) serverTCP_connect();
YSI 15:b2da6ab01a21 157 else serverTCP_event(); break;
YSI 15:b2da6ab01a21 158 default: break;
YSI 1:27f6baabb15e 159 }
YSI 1:27f6baabb15e 160 }
YSI 1:27f6baabb15e 161
YSI 1:27f6baabb15e 162 bool Transmission::serverTCP_connect(void)
YSI 1:27f6baabb15e 163 {
YSI 3:7e15bf0a71f4 164 if(!message.CONNECT)
YSI 3:7e15bf0a71f4 165 if(eth_error("serverTCP_open", _serverTCP.open(_eth)) == NSAPI_ERROR_OK)
YSI 3:7e15bf0a71f4 166 if(eth_error("serverTCP_bind", _serverTCP.bind(message.PORT)) == NSAPI_ERROR_OK)
YSI 3:7e15bf0a71f4 167 if(eth_error("serverTCP_listen", _serverTCP.listen()) == NSAPI_ERROR_OK)
YSI 1:27f6baabb15e 168 {
YSI 3:7e15bf0a71f4 169 _serverTCP.set_blocking(false);
YSI 3:7e15bf0a71f4 170 _serverTCP.sigio(callback(this, &Transmission::serverTCP_event));
YSI 3:7e15bf0a71f4 171 message.CONNECT = true;
YSI 18:15778c8a97a1 172 if(_ethup) _queue->call(_ethup);
YSI 1:27f6baabb15e 173 }
YSI 3:7e15bf0a71f4 174 return message.CONNECT;
YSI 1:27f6baabb15e 175 }
YSI 1:27f6baabb15e 176
YSI 1:27f6baabb15e 177 void Transmission::serverTCP_event(void)
YSI 1:27f6baabb15e 178 {
YSI 14:9e3accc681c4 179 _queue->call(this, &Transmission::serverTCP_accept);
YSI 1:27f6baabb15e 180 }
YSI 1:27f6baabb15e 181
YSI 1:27f6baabb15e 182 void Transmission::serverTCP_accept(void)
YSI 1:27f6baabb15e 183 {
YSI 1:27f6baabb15e 184 if(message.status == GREEN_GLOBAL_UP)
YSI 1:27f6baabb15e 185 {
YSI 1:27f6baabb15e 186 nsapi_error_t ack = NSAPI_ERROR_WOULD_BLOCK;
YSI 1:27f6baabb15e 187 message.status = MAGENTA_ACCEPT;
YSI 3:7e15bf0a71f4 188 _clientTCP = _serverTCP.accept(&ack);
YSI 1:27f6baabb15e 189 switch(ack)
YSI 1:27f6baabb15e 190 {
YSI 1:27f6baabb15e 191 case NSAPI_ERROR_OK:
YSI 14:9e3accc681c4 192 _clientTCP->set_timeout(message.TIMEOUT); // config client bloquante avec timeout sinon limite de transmission a 1072 octets
YSI 1:27f6baabb15e 193 message.status = BLUE_CLIENT;
YSI 1:27f6baabb15e 194 break;
YSI 1:27f6baabb15e 195 case NSAPI_ERROR_NO_CONNECTION:
YSI 4:9a4ab4f406ab 196 eth_state();
YSI 3:7e15bf0a71f4 197 serverTCP_event();
YSI 1:27f6baabb15e 198 break;
YSI 1:27f6baabb15e 199 default:
YSI 4:9a4ab4f406ab 200 eth_state();
YSI 4:9a4ab4f406ab 201 if(ack < NSAPI_ERROR_WOULD_BLOCK) eth_error("serverTCP_accept", ack);
YSI 1:27f6baabb15e 202 break;
YSI 1:27f6baabb15e 203 }
YSI 1:27f6baabb15e 204 }
YSI 1:27f6baabb15e 205 }
YSI 1:27f6baabb15e 206
YSI 4:9a4ab4f406ab 207 void Transmission::eth_state(void)
YSI 4:9a4ab4f406ab 208 {
YSI 4:9a4ab4f406ab 209 switch(_eth->get_connection_status())
YSI 4:9a4ab4f406ab 210 {
YSI 4:9a4ab4f406ab 211 case NSAPI_STATUS_DISCONNECTED: message.status = RED_DISCONNECTED; break;
YSI 4:9a4ab4f406ab 212 case NSAPI_STATUS_CONNECTING: message.status = YELLOW_CONNECTING; break;
YSI 4:9a4ab4f406ab 213 case NSAPI_STATUS_GLOBAL_UP: message.status = GREEN_GLOBAL_UP; break;
YSI 15:b2da6ab01a21 214 default: break;
YSI 4:9a4ab4f406ab 215 }
YSI 4:9a4ab4f406ab 216 }
YSI 4:9a4ab4f406ab 217
YSI 14:9e3accc681c4 218 void Transmission::serial_event(void)
YSI 14:9e3accc681c4 219 {
YSI 14:9e3accc681c4 220 static char buffer[TRANSMISSION_DEFAULT_BUFFER_SIZE] = {0};
YSI 14:9e3accc681c4 221 static uint16_t size = 0;
YSI 14:9e3accc681c4 222 char caractere;
YSI 14:9e3accc681c4 223 _serial->read(&caractere, 1);
YSI 18:15778c8a97a1 224 if(caractere == '\n')
YSI 14:9e3accc681c4 225 {
YSI 14:9e3accc681c4 226 buffer[size] = '\0';
YSI 14:9e3accc681c4 227 size = 0;
YSI 19:6c5777719ece 228 if(_processing) _queue->call(this, &Transmission::preprocessing, buffer, SERIAL_DELIVERY);
YSI 14:9e3accc681c4 229 }
YSI 14:9e3accc681c4 230 else if((caractere > 31) && (caractere < 127) && (size < (TRANSMISSION_DEFAULT_BUFFER_SIZE-2))) buffer[size++] = caractere;
YSI 14:9e3accc681c4 231 }
YSI 14:9e3accc681c4 232
YSI 11:de94dcd67561 233 Transmission::enum_trans_status Transmission::recv(void)
YSI 1:27f6baabb15e 234 {
YSI 16:3ef69ffede76 235 if(_usb)
YSI 15:b2da6ab01a21 236 {
YSI 15:b2da6ab01a21 237 if(_usb->ready())
YSI 15:b2da6ab01a21 238 {
YSI 20:2672d4aea6b7 239 uint8_t buffer[TRANSMISSION_DEFAULT_BUFFER_SIZE] = {0};
YSI 18:15778c8a97a1 240 uint32_t ack = 0, size = 0;
YSI 18:15778c8a97a1 241 do{
YSI 20:2672d4aea6b7 242 ack = NSAPI_ERROR_OK;
YSI 18:15778c8a97a1 243 _usb->receive_nb(&buffer[size], 1, &ack); // un peu plus rapide sur les petits transferts
YSI 18:15778c8a97a1 244 size += ack;
YSI 20:2672d4aea6b7 245 }while((ack > NSAPI_ERROR_OK) && (size < TRANSMISSION_DEFAULT_BUFFER_SIZE-1) && (buffer[size-ack] != '\n'));
YSI 19:6c5777719ece 246 if(size && _processing) preprocessing((char *)buffer, USB_DELIVERY);
YSI 19:6c5777719ece 247 } else _usb->connect();
YSI 15:b2da6ab01a21 248 }
YSI 14:9e3accc681c4 249 if(eth_connect() && (message.status == BLUE_CLIENT))
YSI 1:27f6baabb15e 250 {
YSI 14:9e3accc681c4 251 char buffer[TRANSMISSION_DEFAULT_BUFFER_SIZE] = {0};
YSI 20:2672d4aea6b7 252 nsapi_error_t ack = 0, size = 0;
YSI 20:2672d4aea6b7 253 do{
YSI 20:2672d4aea6b7 254 ack = _clientTCP->recv(&buffer[0], TRANSMISSION_DEFAULT_BUFFER_SIZE-size);
YSI 20:2672d4aea6b7 255 if(ack > NSAPI_ERROR_OK) size += ack;
YSI 20:2672d4aea6b7 256 }while((ack == 536) && (size < TRANSMISSION_DEFAULT_BUFFER_SIZE));
YSI 10:25e049353db5 257 if(ack < NSAPI_ERROR_WOULD_BLOCK) eth_error("clientTCP_recv", ack);
YSI 20:2672d4aea6b7 258 if((ack == NSAPI_ERROR_OK) || (ack == NSAPI_ERROR_NO_CONNECTION))
YSI 18:15778c8a97a1 259 {
YSI 18:15778c8a97a1 260 eth_error("clientTCP_disconnect", _clientTCP->close());
YSI 18:15778c8a97a1 261 eth_state();
YSI 18:15778c8a97a1 262 serverTCP_event();
YSI 18:15778c8a97a1 263 }
YSI 19:6c5777719ece 264 if(size && _processing) preprocessing(buffer, TCP_DELIVERY);
YSI 20:2672d4aea6b7 265 }
YSI 20:2672d4aea6b7 266 else if(!_usb) for(int i = 0; ((i < 10) && (message.status != BLUE_CLIENT)); i++) ThisThread::sleep_for(10ms);
YSI 1:27f6baabb15e 267 return message.status;
YSI 1:27f6baabb15e 268 }
YSI 1:27f6baabb15e 269
YSI 16:3ef69ffede76 270 void Transmission::preprocessing(char *buffer, const enum_trans_delivery delivery)
YSI 16:3ef69ffede76 271 {
YSI 16:3ef69ffede76 272 string cmd(buffer);
YSI 17:9b7100c31466 273 for(char &c : cmd) if(_caseIgnore && (c >= 'a') && (c <= 'z')) c += 'A'-'a';
YSI 16:3ef69ffede76 274 if((cmd.find("HOST: ") != string::npos) || (cmd.find("Host: ") != string::npos))
YSI 19:6c5777719ece 275 send(_processing(cmd), Transmission::HTTP_DELIVERY);
YSI 18:15778c8a97a1 276 else if(!cmd.empty() && (cmd[0] != 22))
YSI 16:3ef69ffede76 277 {
YSI 17:9b7100c31466 278 for(char &c : cmd) if(c == '\n') c = ';';
YSI 17:9b7100c31466 279 istringstream srecv(cmd);
YSI 16:3ef69ffede76 280 string ssend;
YSI 16:3ef69ffede76 281 while(getline(srecv, cmd, ';'))
YSI 16:3ef69ffede76 282 {
YSI 17:9b7100c31466 283 string process = _processing(cmd);
YSI 17:9b7100c31466 284 if(!process.empty()) ssend += (ssend.size() > 0)?(' '+process):process;
YSI 16:3ef69ffede76 285 }
YSI 16:3ef69ffede76 286 send(ssend, delivery);
YSI 16:3ef69ffede76 287 }
YSI 16:3ef69ffede76 288 }
YSI 16:3ef69ffede76 289
YSI 15:b2da6ab01a21 290 nsapi_error_t Transmission::send(const string& buff, const enum_trans_delivery& delivery)
YSI 1:27f6baabb15e 291 {
YSI 1:27f6baabb15e 292 nsapi_error_t ack = NSAPI_ERROR_WOULD_BLOCK;
YSI 1:27f6baabb15e 293 string ssend(buff+"\n");
YSI 19:6c5777719ece 294 if(_usb && !buff.empty() && ((delivery == USB_DELIVERY) || (delivery == ANY_DELIVERY)))
YSI 18:15778c8a97a1 295 {
YSI 18:15778c8a97a1 296 _usb->connect();
YSI 18:15778c8a97a1 297 if(_usb->ready()) _usb->send((uint8_t*)ssend.c_str(), ssend.size());
YSI 18:15778c8a97a1 298 }
YSI 19:6c5777719ece 299 if(_serial && !buff.empty() && ((delivery == SERIAL_DELIVERY) || (delivery == ANY_DELIVERY)))
YSI 11:de94dcd67561 300 ack = _serial->write(ssend.c_str(), ssend.length());
YSI 19:6c5777719ece 301 if(_eth && ((delivery == TCP_DELIVERY) || (delivery == HTTP_DELIVERY) || (delivery == ANY_DELIVERY)))
YSI 1:27f6baabb15e 302 {
YSI 18:15778c8a97a1 303 if((message.status == BLUE_CLIENT) && !buff.empty())
YSI 4:9a4ab4f406ab 304 eth_error("clientTCP_send", ack = _clientTCP->send(ssend.c_str(), ssend.size()));
YSI 19:6c5777719ece 305 if(delivery == HTTP_DELIVERY)
YSI 4:9a4ab4f406ab 306 {
YSI 4:9a4ab4f406ab 307 eth_error("clientTCP_disconnect", _clientTCP->close());
YSI 4:9a4ab4f406ab 308 eth_state();
YSI 4:9a4ab4f406ab 309 serverTCP_event();
YSI 4:9a4ab4f406ab 310 }
YSI 1:27f6baabb15e 311 }
YSI 1:27f6baabb15e 312 return ack;
YSI 1:27f6baabb15e 313 }
YSI 1:27f6baabb15e 314
YSI 14:9e3accc681c4 315 bool Transmission::smtp(const char* MAIL, const char* FROM, const char* SUBJECT, const char* DATA, const char* SERVER)
YSI 1:27f6baabb15e 316 {
YSI 16:3ef69ffede76 317 if(!_eth) return false;
YSI 10:25e049353db5 318 if((!message.DHCP) || (_eth->get_connection_status() != NSAPI_STATUS_GLOBAL_UP)) return false;
YSI 1:27f6baabb15e 319 TCPSocket clientSMTP;
YSI 14:9e3accc681c4 320 clientSMTP.set_timeout(2000);
YSI 14:9e3accc681c4 321 string sMAIL(MAIL), sFROM(FROM), sSUBJECT(SUBJECT), sDATA(DATA), sTO(sMAIL.substr(0, sMAIL.find("@")));
YSI 15:b2da6ab01a21 322 string smtpParams[][7] = { { "", "HELO Mbed " + sFROM + "\r\n", "MAIL FROM: <Mbed." + sFROM + "@UNIVERSITE-PARIS-SACLAY.FR>\r\n", "RCPT TO: <" + sMAIL + ">\r\n", "DATA\r\n", "From: \"Mbed " + sFROM + "\" <Mbed." + sFROM + "@UNIVERSITE-PARIS-SACLAY.FR>\r\nTo: \"" + sTO + "\" <" + sMAIL + ">\r\nSubject:" + sSUBJECT + "\r\n" + sDATA + "\r\n\r\n.\r\n", "QUIT\r\n" },
YSI 15:b2da6ab01a21 323 { "", "HELO Mbed\r\n", "MAIL FROM: <Mbed>\r\n","RCPT TO: <" + sMAIL + ">\r\n", "QUIT\r\n" }};
YSI 1:27f6baabb15e 324 string code;
YSI 1:27f6baabb15e 325 if(eth_error("clientSMTP_open", clientSMTP.open(_eth)) == NSAPI_ERROR_OK)
YSI 1:27f6baabb15e 326 {
YSI 14:9e3accc681c4 327 for(const string& ssend : smtpParams[(sFROM.empty())?1:0])
YSI 1:27f6baabb15e 328 {
YSI 1:27f6baabb15e 329 char buffer[256] = {0};
YSI 14:9e3accc681c4 330 if(code.empty()) { if(eth_error("clientSMTP_connect", clientSMTP.connect(SocketAddress(SERVER, 25))) < NSAPI_ERROR_OK) break; }
YSI 1:27f6baabb15e 331 else if(eth_error("clientSMTP_send", clientSMTP.send(ssend.c_str(), ssend.size())) < NSAPI_ERROR_OK) break;
YSI 1:27f6baabb15e 332 if(eth_error("clientSMTP_recv", clientSMTP.recv(buffer, 256)) < NSAPI_ERROR_OK) break;
YSI 1:27f6baabb15e 333 buffer[3] = 0;
YSI 1:27f6baabb15e 334 code += buffer;
YSI 1:27f6baabb15e 335 if(ssend == "QUIT\r\n") break;
YSI 1:27f6baabb15e 336 }
YSI 1:27f6baabb15e 337 eth_error("clientSMTP_close", clientSMTP.close());
YSI 1:27f6baabb15e 338 }
YSI 1:27f6baabb15e 339 if(sFROM.empty()) return code == "220250250250221";
YSI 12:e22ff63d237c 340 #if MBED_MAJOR_VERSION > 5
YSI 14:9e3accc681c4 341 else if(code != "220250250250354250221") _queue->call_in(60s, this, &Transmission::smtp, MAIL, FROM, SUBJECT, DATA, SERVER);
YSI 12:e22ff63d237c 342 #else
YSI 14:9e3accc681c4 343 else if(code != "220250250250354250221") _queue->call_in(60000, this, &Transmission::smtp, MAIL, FROM, SUBJECT, DATA, SERVER);
YSI 12:e22ff63d237c 344 #endif
YSI 1:27f6baabb15e 345 return code == "220250250250354250221";
YSI 0:2fc6fc3b5e15 346 }
YSI 0:2fc6fc3b5e15 347
YSI 14:9e3accc681c4 348 time_t Transmission::ntp(const char* SERVER)
YSI 6:d6a07fd1548a 349 {
YSI 16:3ef69ffede76 350 if(!_eth) return 0;
YSI 10:25e049353db5 351 if((!message.DHCP) || (_eth->get_connection_status() != NSAPI_STATUS_GLOBAL_UP)) return 0;
YSI 6:d6a07fd1548a 352 time_t timeStamp = 0;
YSI 6:d6a07fd1548a 353 UDPSocket clientNTP;
YSI 14:9e3accc681c4 354 clientNTP.set_timeout(2000);
YSI 6:d6a07fd1548a 355 if(eth_error("clientNTP_open", clientNTP.open(_eth)) == NSAPI_ERROR_OK)
YSI 6:d6a07fd1548a 356 {
YSI 6:d6a07fd1548a 357 uint32_t buffer[12] = { 0b11011, 0 }; // VN = 3 & Mode = 3
YSI 14:9e3accc681c4 358 SocketAddress server(SERVER, 123);
YSI 14:9e3accc681c4 359 string sSERVER(SERVER);
YSI 14:9e3accc681c4 360 if(sSERVER != TRANSMISSION_DEFAULT_NTP_SERVER) eth_error("eth_gethostbyname", _eth->gethostbyname(sSERVER.c_str(), &server));
YSI 14:9e3accc681c4 361 if(eth_error("clientNTP_send", clientNTP.sendto(server, (void*)buffer, sizeof(buffer))) > NSAPI_ERROR_OK)
YSI 6:d6a07fd1548a 362 {
YSI 6:d6a07fd1548a 363 if(eth_error("clientNTP_recv", clientNTP.recvfrom(NULL, (void*)buffer, sizeof(buffer))) > NSAPI_ERROR_OK)
YSI 6:d6a07fd1548a 364 {
YSI 6:d6a07fd1548a 365 timeStamp = ((buffer[10] & 0xFF) << 24) | ((buffer[10] & 0xFF00) << 8) | ((buffer[10] & 0xFF0000UL) >> 8) | ((buffer[10] & 0xFF000000UL) >> 24);
YSI 6:d6a07fd1548a 366 timeStamp -= 2208985200U; // 01/01/1970 Europe
YSI 6:d6a07fd1548a 367 struct tm * tmTimeStamp = localtime(&timeStamp);
YSI 10:25e049353db5 368 if (((tmTimeStamp->tm_mon > 2) && (tmTimeStamp->tm_mon < 10)) || ((tmTimeStamp->tm_mon == 2) && ((tmTimeStamp->tm_mday - tmTimeStamp->tm_wday) > 24)) || ((tmTimeStamp->tm_mon == 9) && ((tmTimeStamp->tm_mday - tmTimeStamp->tm_wday) < 25)))
YSI 7:98b12722e9e2 369 timeStamp += 3600; // DST starts last Sunday of March; 2am (1am UTC), DST ends last Sunday of october; 3am (2am UTC)
YSI 6:d6a07fd1548a 370 }
YSI 6:d6a07fd1548a 371 }
YSI 6:d6a07fd1548a 372 eth_error("clientNTP_close", clientNTP.close());
YSI 6:d6a07fd1548a 373 }
YSI 6:d6a07fd1548a 374 return timeStamp;
YSI 6:d6a07fd1548a 375 }
YSI 6:d6a07fd1548a 376
YSI 0:2fc6fc3b5e15 377 intptr_t Transmission::eth_status(const string& source, const intptr_t& code)
YSI 0:2fc6fc3b5e15 378 {
YSI 14:9e3accc681c4 379 #ifndef NDEBUG
YSI 14:9e3accc681c4 380 ostringstream message;
YSI 0:2fc6fc3b5e15 381 message << "\n" << source << "[" << code;
YSI 0:2fc6fc3b5e15 382 switch(code)
YSI 0:2fc6fc3b5e15 383 {
YSI 0:2fc6fc3b5e15 384 case NSAPI_STATUS_LOCAL_UP: message << "] NSAPI_STATUS_LOCAL_UP < local IP address set >"; break;
YSI 0:2fc6fc3b5e15 385 case NSAPI_STATUS_GLOBAL_UP: message << "] NSAPI_STATUS_GLOBAL_UP < global IP address set >"; break;
YSI 0:2fc6fc3b5e15 386 case NSAPI_STATUS_DISCONNECTED: message << "] NSAPI_STATUS_DISCONNECTED < no connection to network >"; break;
YSI 0:2fc6fc3b5e15 387 case NSAPI_STATUS_CONNECTING: message << "] NSAPI_STATUS_CONNECTING < connecting to network >"; break;
YSI 0:2fc6fc3b5e15 388 case NSAPI_STATUS_ERROR_UNSUPPORTED: message << "] NSAPI_STATUS_ERROR_UNSUPPORTED < unsupported functionality >";break;
YSI 0:2fc6fc3b5e15 389 }
YSI 1:27f6baabb15e 390 _serial->write(message.str().c_str(), message.str().size());
YSI 1:27f6baabb15e 391 #endif
YSI 0:2fc6fc3b5e15 392 return code;
YSI 0:2fc6fc3b5e15 393 }
YSI 0:2fc6fc3b5e15 394
YSI 0:2fc6fc3b5e15 395 nsapi_error_t Transmission::eth_error(const string& source, const nsapi_error_t& code)
YSI 0:2fc6fc3b5e15 396 {
YSI 14:9e3accc681c4 397 #ifndef NDEBUG
YSI 14:9e3accc681c4 398 ostringstream message;
YSI 0:2fc6fc3b5e15 399 message << "\n" << source << "[" << code;
YSI 0:2fc6fc3b5e15 400 switch(code)
YSI 0:2fc6fc3b5e15 401 {
YSI 0:2fc6fc3b5e15 402 case NSAPI_ERROR_OK: message << "] NSAPI_ERROR_OK < no error >"; break;
YSI 0:2fc6fc3b5e15 403 case NSAPI_ERROR_WOULD_BLOCK: message << "] NSAPI_ERROR_WOULD_BLOCK < no data is not available but call is non-blocking >";break;
YSI 0:2fc6fc3b5e15 404 case NSAPI_ERROR_UNSUPPORTED: message << "] NSAPI_ERROR_UNSUPPORTED < unsupported functionality >"; break;
YSI 0:2fc6fc3b5e15 405 case NSAPI_ERROR_PARAMETER: message << "] NSAPI_ERROR_PARAMETER < invalid configuration >"; break;
YSI 0:2fc6fc3b5e15 406 case NSAPI_ERROR_NO_CONNECTION: message << "] NSAPI_ERROR_NO_CONNECTION < not connected to a network >"; break;
YSI 0:2fc6fc3b5e15 407 case NSAPI_ERROR_NO_SOCKET: message << "] NSAPI_ERROR_NO_SOCKET < socket not available for use >"; break;
YSI 0:2fc6fc3b5e15 408 case NSAPI_ERROR_NO_ADDRESS: message << "] NSAPI_ERROR_NO_ADDRESS < IP address is not known >"; break;
YSI 0:2fc6fc3b5e15 409 case NSAPI_ERROR_NO_MEMORY: message << "] NSAPI_ERROR_NO_MEMORY < memory resource not available >"; break;
YSI 0:2fc6fc3b5e15 410 case NSAPI_ERROR_NO_SSID: message << "] NSAPI_ERROR_NO_SSID < ssid not found >"; break;
YSI 0:2fc6fc3b5e15 411 case NSAPI_ERROR_DNS_FAILURE: message << "] NSAPI_ERROR_DNS_FAILURE < DNS failed to complete successfully >"; break;
YSI 0:2fc6fc3b5e15 412 case NSAPI_ERROR_DHCP_FAILURE: message << "] NSAPI_ERROR_DHCP_FAILURE < DHCP failed to complete successfully >"; break;
YSI 0:2fc6fc3b5e15 413 case NSAPI_ERROR_AUTH_FAILURE: message << "] NSAPI_ERROR_AUTH_FAILURE < connection to access point failed >"; break;
YSI 0:2fc6fc3b5e15 414 case NSAPI_ERROR_DEVICE_ERROR: message << "] NSAPI_ERROR_DEVICE_ERROR < failure interfacing with the network processor >"; break;
YSI 0:2fc6fc3b5e15 415 case NSAPI_ERROR_IN_PROGRESS: message << "] NSAPI_ERROR_IN_PROGRESS < operation (eg connect) in progress >"; break;
YSI 0:2fc6fc3b5e15 416 case NSAPI_ERROR_ALREADY: message << "] NSAPI_ERROR_ALREADY < operation (eg connect) already in progress >"; break;
YSI 0:2fc6fc3b5e15 417 case NSAPI_ERROR_IS_CONNECTED: message << "] NSAPI_ERROR_IS_CONNECTED < socket is already connected >"; break;
YSI 0:2fc6fc3b5e15 418 case NSAPI_ERROR_CONNECTION_LOST: message << "] NSAPI_ERROR_CONNECTION_LOST < connection lost >"; break;
YSI 0:2fc6fc3b5e15 419 case NSAPI_ERROR_CONNECTION_TIMEOUT: message << "] NSAPI_ERROR_CONNECTION_TIMEOUT < connection timed out >"; break;
YSI 0:2fc6fc3b5e15 420 case NSAPI_ERROR_ADDRESS_IN_USE: message << "] NSAPI_ERROR_ADDRESS_IN_USE < Address already in use >"; break;
YSI 0:2fc6fc3b5e15 421 case NSAPI_ERROR_TIMEOUT: message << "] NSAPI_ERROR_TIMEOUT < operation timed out >"; break;
YSI 0:2fc6fc3b5e15 422 case NSAPI_ERROR_BUSY: message << "] NSAPI_ERROR_BUSY < device is busy and cannot accept new operation >"; break;
YSI 0:2fc6fc3b5e15 423 default: message << "] NSAPI_ERROR < unknow code >"; break;
YSI 0:2fc6fc3b5e15 424 }
YSI 1:27f6baabb15e 425 if(code < NSAPI_ERROR_OK) _serial->write(message.str().c_str(), message.str().size());
YSI 1:27f6baabb15e 426 #endif
YSI 0:2fc6fc3b5e15 427 return code;
YSI 0:2fc6fc3b5e15 428 }